test: stackovf.c Source File

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 }