Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

stackovf.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 StackOvf.c 00008 00009 Abstract: 00010 00011 The file lock package provides a worker thread to handle 00012 stack overflow conditions in the file systems. When the 00013 file system detects that it is near the end of its stack 00014 during a paging I/O read request it will post the request 00015 to this extra thread. 00016 00017 Author: 00018 00019 Gary Kimura [GaryKi] 24-Nov-1992 00020 00021 Revision History: 00022 00023 --*/ 00024 00025 #include "FsRtlP.h" 00026 // 00027 // Queue object that is used to hold work queue entries and synchronize 00028 // worker thread activity. 00029 // 00030 00031 KQUEUE FsRtlWorkerQueues[2]; 00032 00033 // 00034 // Define a tag for general pool allocations from this module 00035 // 00036 00037 #undef MODULE_POOL_TAG 00038 #define MODULE_POOL_TAG ('srSF') 00039 00040 00041 // 00042 // Local Support Routine 00043 // 00044 00045 VOID 00046 FsRtlStackOverflowRead ( 00047 IN PVOID Context 00048 ); 00049 00050 VOID 00051 FsRtlpPostStackOverflow ( 00052 IN PVOID Context, 00053 IN PKEVENT Event, 00054 IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine, 00055 IN BOOLEAN PagingFile 00056 ); 00057 00058 // 00059 // Procedure prototype for the worker thread. 00060 // 00061 00062 VOID 00063 FsRtlWorkerThread( 00064 IN PVOID StartContext 00065 ); 00066 00067 // 00068 // The following type is used to store an enqueue work item 00069 // 00070 00071 typedef struct _STACK_OVERFLOW_ITEM { 00072 00073 WORK_QUEUE_ITEM Item; 00074 00075 // 00076 // This is the call back routine 00077 // 00078 00079 PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine; 00080 00081 // 00082 // Here are the parameters for the call back routine 00083 // 00084 00085 PVOID Context; 00086 PKEVENT Event; 00087 00088 } STACK_OVERFLOW_ITEM; 00089 typedef STACK_OVERFLOW_ITEM *PSTACK_OVERFLOW_ITEM; 00090 00091 00092 #ifdef ALLOC_PRAGMA 00093 #pragma alloc_text(INIT, FsRtlInitializeWorkerThread) 00094 #endif 00095 00096 00097 00098 NTSTATUS 00099 FsRtlInitializeWorkerThread ( 00100 VOID 00101 ) 00102 { 00103 OBJECT_ATTRIBUTES ObjectAttributes; 00104 HANDLE Thread; 00105 ULONG i; 00106 00107 // 00108 // Create worker threads to handle normal and paging overflow reads. 00109 // 00110 00111 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 00112 00113 for (i=0; i < 2; i++) { 00114 00115 // 00116 // Initialize the FsRtl stack overflow work Queue objects. 00117 // 00118 00119 KeInitializeQueue(&FsRtlWorkerQueues[i], 0); 00120 00121 if (!NT_SUCCESS(PsCreateSystemThread(&Thread, 00122 THREAD_ALL_ACCESS, 00123 &ObjectAttributes, 00124 0L, 00125 NULL, 00126 FsRtlWorkerThread, 00127 ULongToPtr( i )))) { 00128 00129 return FALSE; 00130 } 00131 } 00132 00133 ZwClose( Thread ); 00134 00135 return TRUE; 00136 } 00137 00138 VOID 00139 FsRtlPostStackOverflow ( 00140 IN PVOID Context, 00141 IN PKEVENT Event, 00142 IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine 00143 ) 00144 00145 /*++ 00146 00147 Routine Description: 00148 00149 This routines posts a stack overflow item to the stack overflow 00150 thread and returns. 00151 00152 Arguments: 00153 00154 Context - Supplies the context to pass to the stack overflow 00155 call back routine. If the low order bit is set, then 00156 this overflow was a read to a paging file. 00157 00158 Event - Supplies a pointer to an event to pass to the stack 00159 overflow call back routine. 00160 00161 StackOverflowRoutine - Supplies the call back to use when 00162 processing the request in the overflow thread. 00163 00164 Return Value: 00165 00166 None. 00167 00168 --*/ 00169 00170 { 00171 FsRtlpPostStackOverflow( Context, Event, StackOverflowRoutine, FALSE ); 00172 return; 00173 } 00174 00175 00176 VOID 00177 FsRtlPostPagingFileStackOverflow ( 00178 IN PVOID Context, 00179 IN PKEVENT Event, 00180 IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine 00181 ) 00182 00183 /*++ 00184 00185 Routine Description: 00186 00187 This routines posts a stack overflow item to the stack overflow 00188 thread and returns. 00189 00190 Arguments: 00191 00192 Context - Supplies the context to pass to the stack overflow 00193 call back routine. If the low order bit is set, then 00194 this overflow was a read to a paging file. 00195 00196 Event - Supplies a pointer to an event to pass to the stack 00197 overflow call back routine. 00198 00199 StackOverflowRoutine - Supplies the call back to use when 00200 processing the request in the overflow thread. 00201 00202 Return Value: 00203 00204 None. 00205 00206 --*/ 00207 00208 { 00209 FsRtlpPostStackOverflow( Context, Event, StackOverflowRoutine, TRUE ); 00210 return; 00211 } 00212 00213 00214 VOID 00215 FsRtlpPostStackOverflow ( 00216 IN PVOID Context, 00217 IN PKEVENT Event, 00218 IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine, 00219 IN BOOLEAN PagingFile 00220 ) 00221 00222 /*++ 00223 00224 Routine Description: 00225 00226 This routines posts a stack overflow item to the stack overflow 00227 thread and returns. 00228 00229 Arguments: 00230 00231 Context - Supplies the context to pass to the stack overflow 00232 call back routine. If the low order bit is set, then 00233 this overflow was a read to a paging file. 00234 00235 Event - Supplies a pointer to an event to pass to the stack 00236 overflow call back routine. 00237 00238 StackOverflowRoutine - Supplies the call back to use when 00239 processing the request in the overflow thread. 00240 00241 PagingFile - Indicates if the read is destined to a paging file. 00242 00243 Return Value: 00244 00245 None. 00246 00247 --*/ 00248 00249 { 00250 PSTACK_OVERFLOW_ITEM StackOverflowItem; 00251 00252 // 00253 // Allocate a stack overflow work item it will later be deallocated by 00254 // the stack overflow thread 00255 // 00256 00257 StackOverflowItem = FsRtlpAllocatePool( PagingFile ? 00258 NonPagedPoolMustSucceed : 00259 NonPagedPool, 00260 sizeof(STACK_OVERFLOW_ITEM) ); 00261 00262 // 00263 // Fill in the fields in the new item 00264 // 00265 00266 StackOverflowItem->Context = Context; 00267 StackOverflowItem->Event = Event; 00268 StackOverflowItem->StackOverflowRoutine = StackOverflowRoutine; 00269 00270 ExInitializeWorkItem( &StackOverflowItem->Item, 00271 &FsRtlStackOverflowRead, 00272 StackOverflowItem ); 00273 00274 // 00275 // Safely add it to the overflow queue 00276 // 00277 00278 KeInsertQueue( &FsRtlWorkerQueues[PagingFile], 00279 &StackOverflowItem->Item.List ); 00280 00281 // 00282 // And return to our caller 00283 // 00284 00285 return; 00286 } 00287 00288 00289 // 00290 // Local Support Routine 00291 // 00292 00293 VOID 00294 FsRtlStackOverflowRead ( 00295 IN PVOID Context 00296 ) 00297 00298 /*++ 00299 00300 Routine Description: 00301 00302 This routine processes all of the stack overflow request posted by 00303 the various file systems 00304 00305 Arguments: 00306 00307 Return Value: 00308 00309 None. 00310 00311 --*/ 00312 00313 { 00314 PSTACK_OVERFLOW_ITEM StackOverflowItem; 00315 00316 // 00317 // Since stack overflow reads are always recursive, set the 00318 // TopLevelIrp field appropriately so that recurive reads 00319 // from this point will not think they are top level. 00320 // 00321 00322 PsGetCurrentThread()->TopLevelIrp = FSRTL_FSP_TOP_LEVEL_IRP; 00323 00324 // 00325 // Get a pointer to the stack overflow item and then call 00326 // the callback routine to do the work 00327 // 00328 00329 StackOverflowItem = (PSTACK_OVERFLOW_ITEM)Context; 00330 00331 (StackOverflowItem->StackOverflowRoutine)(StackOverflowItem->Context, 00332 StackOverflowItem->Event); 00333 00334 // 00335 // Deallocate the work item and then go back to the loop to 00336 // to wait for another work item 00337 // 00338 00339 ExFreePool( StackOverflowItem ); 00340 00341 PsGetCurrentThread()->TopLevelIrp = (ULONG_PTR)NULL; 00342 } 00343 00344 VOID 00345 FsRtlWorkerThread( 00346 IN PVOID StartContext 00347 ) 00348 00349 { 00350 PLIST_ENTRY Entry; 00351 PWORK_QUEUE_ITEM WorkItem; 00352 ULONG PagingFile = (ULONG)(ULONG_PTR)StartContext; 00353 00354 // 00355 // Set our priority to low realtime, or +1 for PagingFile. 00356 // 00357 00358 (VOID)KeSetPriorityThread( &PsGetCurrentThread()->Tcb, 00359 LOW_REALTIME_PRIORITY + PagingFile ); 00360 00361 // 00362 // Loop forever waiting for a work queue item, calling the processing 00363 // routine, and then waiting for another work queue item. 00364 // 00365 00366 do { 00367 00368 // 00369 // Wait until something is put in the queue. 00370 // 00371 // By specifying a wait mode of KernelMode, the thread's kernel stack is 00372 // NOT swappable 00373 // 00374 00375 Entry = KeRemoveQueue(&FsRtlWorkerQueues[PagingFile], KernelMode, NULL); 00376 WorkItem = CONTAINING_RECORD(Entry, WORK_QUEUE_ITEM, List); 00377 00378 // 00379 // Execute the specified routine. 00380 // 00381 00382 (WorkItem->WorkerRoutine)(WorkItem->Parameter); 00383 if (KeGetCurrentIrql() != 0) { 00384 KeBugCheckEx( 00385 IRQL_NOT_LESS_OR_EQUAL, 00386 (ULONG_PTR)WorkItem->WorkerRoutine, 00387 (ULONG_PTR)KeGetCurrentIrql(), 00388 (ULONG_PTR)WorkItem->WorkerRoutine, 00389 (ULONG_PTR)WorkItem 00390 ); 00391 } 00392 00393 } while(TRUE); 00394 }

Generated on Sat May 15 19:41:52 2004 for test by doxygen 1.3.7