예제 #1
0
NTSTATUS
FsRtlInitializeWorkerThread (
    VOID
)
{
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE Thread;
    ULONG i;

    //
    // Create worker threads to handle normal and paging overflow reads.
    //

    InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);

    for (i=0; i < 2; i++) {

        //
        // Initialize the FsRtl stack overflow work Queue objects.
        //

        KeInitializeQueue(&FsRtlWorkerQueues[i], 0);

        if (!NT_SUCCESS(PsCreateSystemThread(&Thread,
                                             THREAD_ALL_ACCESS,
                                             &ObjectAttributes,
                                             0L,
                                             NULL,
                                             FsRtlWorkerThread,
                                             (PVOID)i))) {

            return FALSE;
        }
    }

    ZwClose( Thread );

    return TRUE;
}
예제 #2
0
/*
 * @implemented
 */
NTSTATUS
NTAPI
INIT_FUNCTION
FsRtlInitializeWorkerThread(VOID)
{
    ULONG i;
    NTSTATUS Status;
    HANDLE ThreadHandle;
    OBJECT_ATTRIBUTES ObjectAttributes;

    /* Initialize each queue we have */
    for (i = 0; i < FSRTLP_MAX_QUEUES; ++i)
    {
        InitializeObjectAttributes(&ObjectAttributes,
                                   NULL,
                                   0,
                                   NULL,
                                   NULL);

        /* Initialize the queue and its associated thread and pass it the queue ID */
        KeInitializeQueue(&FsRtlWorkerQueues[i], 0);
        Status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, &ObjectAttributes,
                                      0, 0, FsRtlWorkerThread, (PVOID)i);
        if (!NT_SUCCESS(Status))
        {
            return Status;
        }

        /* Don't leak handle */
        ZwClose(ThreadHandle);
    }

    /* Also initialize our fallback event, set it to ensure it's already usable */
    KeInitializeEvent(&StackOverflowFallbackSerialEvent, SynchronizationEvent, TRUE);

    return Status;
}
예제 #3
0
파일: work.c 프로젝트: killvxk/NT_OS
/*++
 * @name ExpInitializeWorkerThreads
 *
 *     The ExpInitializeWorkerThreads routine initializes worker thread and
 *     work queue support.
 *
 * @param None.
 *
 * @return None.
 *
 * @remarks This routine is only called once during system initialization.
 *
 *--*/
VOID
INIT_FUNCTION
NTAPI
ExpInitializeWorkerThreads(VOID)
{
    ULONG WorkQueueType;
    ULONG CriticalThreads, DelayedThreads;
    HANDLE ThreadHandle;
    PETHREAD Thread;
    ULONG i;

    /* Setup the stack swap support */
    ExInitializeFastMutex(&ExpWorkerSwapinMutex);
    InitializeListHead(&ExpWorkerListHead);
    ExpWorkersCanSwap = TRUE;

    /* Set the number of critical and delayed threads. We shouldn't hardcode */
    DelayedThreads = EX_DELAYED_WORK_THREADS;
    CriticalThreads = EX_CRITICAL_WORK_THREADS;

    /* Protect against greedy registry modifications */
    ExpAdditionalDelayedWorkerThreads =
        min(ExpAdditionalDelayedWorkerThreads, 16);
    ExpAdditionalCriticalWorkerThreads =
        min(ExpAdditionalCriticalWorkerThreads, 16);

    /* Calculate final count */
    DelayedThreads += ExpAdditionalDelayedWorkerThreads;
    CriticalThreads += ExpAdditionalCriticalWorkerThreads;

    /* Initialize the Array */
    for (WorkQueueType = 0; WorkQueueType < MaximumWorkQueue; WorkQueueType++)
    {
        /* Clear the structure and initialize the queue */
        RtlZeroMemory(&ExWorkerQueue[WorkQueueType], sizeof(EX_WORK_QUEUE));
        KeInitializeQueue(&ExWorkerQueue[WorkQueueType].WorkerQueue, 0);
    }

    /* Dynamic threads are only used for the critical queue */
    ExWorkerQueue[CriticalWorkQueue].Info.MakeThreadsAsNecessary = TRUE;

    /* Initialize the balance set manager events */
    KeInitializeEvent(&ExpThreadSetManagerEvent, SynchronizationEvent, FALSE);
    KeInitializeEvent(&ExpThreadSetManagerShutdownEvent,
                      NotificationEvent,
                      FALSE);

    /* Create the built-in worker threads for the critical queue */
    for (i = 0; i < CriticalThreads; i++)
    {
        /* Create the thread */
        ExpCreateWorkerThread(CriticalWorkQueue, FALSE);
        ExpCriticalWorkerThreads++;
    }

    /* Create the built-in worker threads for the delayed queue */
    for (i = 0; i < DelayedThreads; i++)
    {
        /* Create the thread */
        ExpCreateWorkerThread(DelayedWorkQueue, FALSE);
        ExpDelayedWorkerThreads++;
    }

    /* Create the built-in worker thread for the hypercritical queue */
    ExpCreateWorkerThread(HyperCriticalWorkQueue, FALSE);

    /* Create the balance set manager thread */
    PsCreateSystemThread(&ThreadHandle,
                         THREAD_ALL_ACCESS,
                         NULL,
                         0,
                         NULL,
                         ExpWorkerThreadBalanceManager,
                         NULL);

    /* Get a pointer to it for the shutdown process */
    ObReferenceObjectByHandle(ThreadHandle,
                              THREAD_ALL_ACCESS,
                              NULL,
                              KernelMode,
                              (PVOID*)&Thread,
                              NULL);
    ExpWorkerThreadBalanceManagerPtr = Thread;

    /* Close the handle and return */
    ObCloseHandle(ThreadHandle, KernelMode);
}
예제 #4
0
파일: worker.c 프로젝트: BaoYu0721/WRK-1.2
NTSTATUS
ExpWorkerInitialization (
    VOID
    )
{
    ULONG Index;
    OBJECT_ATTRIBUTES ObjectAttributes;
    ULONG NumberOfDelayedThreads;
    ULONG NumberOfCriticalThreads;
    ULONG NumberOfThreads;
    NTSTATUS Status;
    HANDLE Thread;
    BOOLEAN NtAs;
    WORK_QUEUE_TYPE WorkQueueType;

    ExInitializeFastMutex (&ExpWorkerSwapinMutex);
    InitializeListHead (&ExpWorkerListHead);
    ExpWorkersCanSwap = TRUE;

    //
    // Set the number of worker threads based on the system size.
    //

    NtAs = MmIsThisAnNtAsSystem();

    NumberOfCriticalThreads = MEDIUM_NUMBER_OF_THREADS;

    //
    // Incremented boot time number of delayed threads.
    // We did this in Windows XP, because 3COM NICs would take a long
    // time with the network stack tying up the delayed worker threads.
    // When Mm would need a worker thread to load a driver on the critical
    // path of boot, it would also get stuck for a few seconds and hurt
    // boot times. Ideally we'd spawn new delayed threads as necessary as
    // well to prevent such contention from hurting boot and resume.
    //

    NumberOfDelayedThreads = MEDIUM_NUMBER_OF_THREADS + 4;

    switch (MmQuerySystemSize()) {

        case MmSmallSystem:
            break;

        case MmMediumSystem:
            if (NtAs) {
                NumberOfCriticalThreads += MEDIUM_NUMBER_OF_THREADS;
            }
            break;

        case MmLargeSystem:
            NumberOfCriticalThreads = LARGE_NUMBER_OF_THREADS;
            if (NtAs) {
                NumberOfCriticalThreads += LARGE_NUMBER_OF_THREADS;
            }
            break;

        default:
            break;
    }

    //
    // Initialize the work Queue objects.
    //

    if (ExpAdditionalCriticalWorkerThreads > MAX_ADDITIONAL_THREADS) {
        ExpAdditionalCriticalWorkerThreads = MAX_ADDITIONAL_THREADS;
    }

    if (ExpAdditionalDelayedWorkerThreads > MAX_ADDITIONAL_THREADS) {
        ExpAdditionalDelayedWorkerThreads = MAX_ADDITIONAL_THREADS;
    }

    //
    // Initialize the ExWorkerQueue[] array.
    //

    RtlZeroMemory (&ExWorkerQueue[0], MaximumWorkQueue * sizeof(EX_WORK_QUEUE));

    for (WorkQueueType = 0; WorkQueueType < MaximumWorkQueue; WorkQueueType += 1) {

        KeInitializeQueue (&ExWorkerQueue[WorkQueueType].WorkerQueue, 0);
        ExWorkerQueue[WorkQueueType].Info.WaitMode = UserMode;
    }

    //
    // Always make stack for this thread resident
    // so that worker pool deadlock magic can run
    // even when what we are trying to do is inpage
    // the hyper critical worker thread's stack.
    // Without this fix, we hold the process lock
    // but this thread's stack can't come in, and
    // the deadlock detection cannot create new threads
    // to break the system deadlock.
    //

    ExWorkerQueue[HyperCriticalWorkQueue].Info.WaitMode = KernelMode;

    if (NtAs) {
        ExWorkerQueue[CriticalWorkQueue].Info.WaitMode = KernelMode;
    }

    //
    // We only create dynamic threads for the critical work queue (note
    // this doesn't apply to dynamic threads created to break deadlocks.)
    //
    // The rationale is this: folks who use the delayed work queue are
    // not time critical, and the hypercritical queue is used rarely
    // by folks who are non-blocking.
    //

    ExWorkerQueue[CriticalWorkQueue].Info.MakeThreadsAsNecessary = 1;

    //
    // Initialize the global thread set manager events
    //

    KeInitializeEvent (&ExpThreadSetManagerEvent,
                       SynchronizationEvent,
                       FALSE);

    KeInitializeEvent (&ExpThreadSetManagerShutdownEvent,
                       SynchronizationEvent,
                       FALSE);

    //
    // Create the desired number of executive worker threads for each
    // of the work queues.
    //

    //
    // Create the builtin critical worker threads.
    //

    NumberOfThreads = NumberOfCriticalThreads + ExpAdditionalCriticalWorkerThreads;
    for (Index = 0; Index < NumberOfThreads; Index += 1) {

        //
        // Create a worker thread to service the critical work queue.
        //

        Status = ExpCreateWorkerThread (CriticalWorkQueue, FALSE);

        if (!NT_SUCCESS(Status)) {
            break;
        }
    }

    ExCriticalWorkerThreads += Index;

    //
    // Create the delayed worker threads.
    //

    NumberOfThreads = NumberOfDelayedThreads + ExpAdditionalDelayedWorkerThreads;
    for (Index = 0; Index < NumberOfThreads; Index += 1) {

        //
        // Create a worker thread to service the delayed work queue.
        //

        Status = ExpCreateWorkerThread (DelayedWorkQueue, FALSE);

        if (!NT_SUCCESS(Status)) {
            break;
        }
    }

    ExDelayedWorkerThreads += Index;

    //
    // Create the hypercritical worker thread.
    //

    Status = ExpCreateWorkerThread (HyperCriticalWorkQueue, FALSE);

    //
    // Create the worker thread set manager thread.
    //

    InitializeObjectAttributes (&ObjectAttributes, NULL, 0, NULL, NULL);

    Status = PsCreateSystemThread (&Thread,
                                   THREAD_ALL_ACCESS,
                                   &ObjectAttributes,
                                   0,
                                   NULL,
                                   ExpWorkerThreadBalanceManager,
                                   NULL);

    if (NT_SUCCESS(Status)) {
        Status = ObReferenceObjectByHandle (Thread,
                                            SYNCHRONIZE,
                                            NULL,
                                            KernelMode,
                                            &ExpWorkerThreadBalanceManagerPtr,
                                            NULL);
        ZwClose (Thread);
    }

    return Status;
}
예제 #5
0
NTSTATUS
NtCreateIoCompletion (
    __out PHANDLE IoCompletionHandle,
    __in ACCESS_MASK DesiredAccess,
    __in_opt POBJECT_ATTRIBUTES ObjectAttributes,
    __in ULONG Count OPTIONAL
    )

/*++

Routine Description:

    This function creates an I/O completion object, sets the maximum
    target concurrent thread count to the specified value, and opens
    a handle to the object with the specified desired access.

Arguments:

    IoCompletionHandle - Supplies a pointer to a variable that receives
        the I/O completion object handle.

    DesiredAccess - Supplies the desired types of access for the I/O
        completion object.

    ObjectAttributes - Supplies a pointer to an object attributes structure.

    Count - Supplies the target maximum  number of threads that should
        be concurrently active. If this parameter is not specified, then
        the number of processors is used.

Return Value:

    STATUS_SUCCESS is returned if the function is success. Otherwise, an
    error status is returned.

--*/

{

    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode;
    PVOID IoCompletion;
    NTSTATUS Status;

    //
    // Establish an exception handler, probe the output handle address, and
    // attempt to create an I/O completion object. If the probe fails, then
    // return the exception code as the service status. Otherwise, return the
    // status value returned by the object insertion routine.
    //

    try {

        //
        // Get previous processor mode and probe output handle address if
        // necessary.
        //

        PreviousMode = KeGetPreviousMode();
        if (PreviousMode != KernelMode) {
            ProbeForWriteHandle(IoCompletionHandle);
        }

        //
        // Allocate I/O completion object.
        //

        Status = ObCreateObject(PreviousMode,
                                IoCompletionObjectType,
                                ObjectAttributes,
                                PreviousMode,
                                NULL,
                                sizeof(KQUEUE),
                                0,
                                0,
                                (PVOID *)&IoCompletion);

        //
        // If the I/O completion object was successfully allocated, then
        // initialize the object and attempt to insert it in the handle
        // table of the current process.
        //

        if (NT_SUCCESS(Status)) {
            KeInitializeQueue((PKQUEUE)IoCompletion, Count);
            Status = ObInsertObject(IoCompletion,
                                    NULL,
                                    DesiredAccess,
                                    0,
                                    (PVOID *)NULL,
                                    &Handle);

            //
            // If the I/O completion object was successfully inserted in
            // the handle table of the current process, then attempt to
            // write the handle value. If the write attempt fails, then
            // do not report an error. When the caller attempts to access
            // the handle value, an access violation will occur.
            //

            if (NT_SUCCESS(Status)) {
                try {
                    *IoCompletionHandle = Handle;

                } except(ExSystemExceptionFilter()) {
                    NOTHING;
                }
            }
        }

    //
    // If an exception occurs during the probe of the output handle address,
    // then always handle the exception and return the exception code as the
    // status value.
    //

    } except(ExSystemExceptionFilter()) {
        Status = GetExceptionCode();
    }

    //
    // Return service status.
    //

    return Status;
}
예제 #6
0
NTSTATUS
FsRtlInitializeWorkerThread (
    VOID
    )
{
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE Thread;
    ULONG i;
    NTSTATUS Status = STATUS_SUCCESS;

    //
    // Create worker threads to handle normal and paging overflow reads.
    //

    InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);

    for (i=0; i < 2; i++) {

        //
        // Initialize the FsRtl stack overflow work Queue objects.
        //

        KeInitializeQueue(&FsRtlWorkerQueues[i], 0);

        Status = PsCreateSystemThread( &Thread,
                                       THREAD_ALL_ACCESS,
                                       &ObjectAttributes,
                                       0L,
                                       NULL,
                                       FsRtlWorkerThread,
                                       ULongToPtr( i ));
        
        if (!NT_SUCCESS( Status )) {

            return Status;
        }

        ZwClose( Thread );
    }

    //
    //  Initialize the serial workitem so we can guarantee to post items
    //  for paging files to the worker threads.
    //

    KeInitializeEvent( &StackOverflowFallbackSerialEvent, SynchronizationEvent, TRUE );

    //
    // Pass a NOP routine through FsRtlPostStackOverfow() in order to flush out
    // any prefetchw instructions that may lie in that path.  Otherwise we'll
    // try to patch the prefetchw instruction when we can ill afford the stack
    // space.
    // 

#if defined(_AMD64_)

    FsRtlPostStackOverflow( NULL, NULL, FsRtlpNopStackOverflowRoutine );
    FsRtlPostPagingFileStackOverflow( NULL, NULL, FsRtlpNopStackOverflowRoutine );

#endif

    return Status;
}