示例#1
0
/*
 * @implemented
 */
VOID
NTAPI
FsRtlpPostStackOverflow(IN PVOID Context,
                        IN PKEVENT Event,
                        IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine,
                        IN BOOLEAN IsPaging)
{
    PSTACK_OVERFLOW_WORK_ITEM WorkItem;

    /* Try to allocate a work item */
    WorkItem = ExAllocatePoolWithTag(NonPagedPool, sizeof(STACK_OVERFLOW_WORK_ITEM), 'FSrs');
    if (WorkItem == NULL)
    {
        /* If we failed, and we are not a paging file, just raise an error */
        if (!IsPaging)
        {
            RtlRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
        }

        /* Otherwise, wait for fallback workitem to be available and use it */
        KeWaitForSingleObject(&StackOverflowFallbackSerialEvent, Executive, KernelMode, FALSE, NULL);
        WorkItem = &StackOverflowFallback;
    }

    /* Initialize work item */
    WorkItem->Context = Context;
    WorkItem->Event = Event;
    WorkItem->Routine = StackOverflowRoutine;
    ExInitializeWorkItem(&WorkItem->WorkItem, FsRtlStackOverflowRead, WorkItem);

    /* And queue it in the appropriate queue (paging or not?) */
    KeInsertQueue(&FsRtlWorkerQueues[IsPaging], &WorkItem->WorkItem.List);
}
示例#2
0
VOID
ExpShutdownWorkerThreads (
    VOID
    )
{
    PULONG QueueEnable;
    SHUTDOWN_WORK_ITEM ShutdownItem;

    if ((PoCleanShutdownEnabled () & PO_CLEAN_SHUTDOWN_WORKERS) == 0) {
        return;
    }

    ASSERT (KeGetCurrentThread()->Queue
           == &ExWorkerQueue[PO_SHUTDOWN_QUEUE].WorkerQueue);

    //
    // Mark the queues as terminating.
    //

    QueueEnable = (PULONG)&ExWorkerQueue[DelayedWorkQueue].Info.QueueWorkerInfo;

    RtlInterlockedSetBitsDiscardReturn (QueueEnable, EX_WORKER_QUEUE_DISABLED);

    QueueEnable = (PULONG)&ExWorkerQueue[CriticalWorkQueue].Info.QueueWorkerInfo;
    RtlInterlockedSetBitsDiscardReturn (QueueEnable, EX_WORKER_QUEUE_DISABLED);

    //
    // Queue the shutdown work item to the delayed work queue.  After
    // all currently queued work items are complete, this will fire,
    // repeatedly taking out every worker thread in every queue until
    // they're all done.
    //

    ExInitializeWorkItem (&ShutdownItem.WorkItem,
                          &ExpShutdownWorker,
                          &ShutdownItem);

    ShutdownItem.QueueType = DelayedWorkQueue;
    ShutdownItem.PrevThread = NULL;

    KeInsertQueue (&ExWorkerQueue[DelayedWorkQueue].WorkerQueue,
                   &ShutdownItem.WorkItem.List);

    //
    // Wait for all of the workers and the balancer to exit.
    //

    if (ExpWorkerThreadBalanceManagerPtr != NULL) {

        KeWaitForSingleObject(ExpWorkerThreadBalanceManagerPtr,
                              Executive,
                              KernelMode,
                              FALSE,
                              NULL);

        ASSERT(!ShutdownItem.PrevThread);

        ObDereferenceObject(ExpWorkerThreadBalanceManagerPtr);
    }
}
示例#3
0
文件: work.c 项目: killvxk/NT_OS
/*++
 * @name ExQueueWorkItem
 * @implemented NT4
 *
 *     The ExQueueWorkItem routine acquires rundown protection for
 *     the specified descriptor.
 *
 * @param WorkItem
 *        Pointer to an initialized Work Queue Item structure. This structure
 *        must be located in nonpaged pool memory.
 *
 * @param QueueType
 *        Type of the queue to use for this item. Can be one of the following:
 *          - DelayedWorkQueue
 *          - CriticalWorkQueue
 *          - HyperCriticalWorkQueue
 *
 * @return None.
 *
 * @remarks This routine is obsolete. Use IoQueueWorkItem instead.
 *
 *          Callers of this routine must be running at IRQL <= DISPATCH_LEVEL.
 *
 *--*/
VOID
NTAPI
ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem,
                IN WORK_QUEUE_TYPE QueueType)
{
    PEX_WORK_QUEUE WorkQueue = &ExWorkerQueue[QueueType];
    ASSERT(QueueType < MaximumWorkQueue);
    ASSERT(WorkItem->List.Flink == NULL);

    /* Don't try to trick us */
    if ((ULONG_PTR)WorkItem->WorkerRoutine < MmUserProbeAddress)
    {
        /* Bugcheck the system */
        KeBugCheckEx(WORKER_INVALID,
                     1,
                     (ULONG_PTR)WorkItem,
                     (ULONG_PTR)WorkItem->WorkerRoutine,
                     0);
    }

    /* Insert the Queue */
    KeInsertQueue(&WorkQueue->WorkerQueue, &WorkItem->List);
    ASSERT(!WorkQueue->Info.QueueDisabled);

    /*
     * Check if we need a new thread. Our decision is as follows:
     *  - This queue type must support Dynamic Threads (duh!)
     *  - It actually has to have unprocessed items
     *  - We have CPUs which could be handling another thread
     *  - We haven't abused our usage of dynamic threads.
     */
    if ((WorkQueue->Info.MakeThreadsAsNecessary) &&
        (!IsListEmpty(&WorkQueue->WorkerQueue.EntryListHead)) &&
        (WorkQueue->WorkerQueue.CurrentCount <
         WorkQueue->WorkerQueue.MaximumCount) &&
        (WorkQueue->DynamicThreadCount < 16))
    {
        /* Let the balance manager know about it */
        DPRINT1("Requesting a new thread. CurrentCount: %d. MaxCount: %d\n",
                WorkQueue->WorkerQueue.CurrentCount,
                WorkQueue->WorkerQueue.MaximumCount);
        KeSetEvent(&ExpThreadSetManagerEvent, 0, FALSE);
    }
}
示例#4
0
LOGICAL
ExpCheckQueueShutdown (
    IN WORK_QUEUE_TYPE QueueType,
    IN PSHUTDOWN_WORK_ITEM ShutdownItem
    )
{
    ULONG CountForQueueEmpty;

    if (PO_SHUTDOWN_QUEUE == QueueType) {
        CountForQueueEmpty = 1;
    }
    else {
        CountForQueueEmpty = 0;
    }

    //
    // Note that using interlocked sequences to increment the worker count
    // and decrement it to CountForQueueEmpty ensures that once it
    // *is* equal to CountForQueueEmpty and the disabled flag is set,
    // we won't be incrementing it any more, so we're safe making this
    // check without locks.
    //
    // See ExpWorkerThread, ExpShutdownWorker, and ExpShutdownWorkerThreads.
    //

    if (ExWorkerQueue[QueueType].Info.WorkerCount > CountForQueueEmpty) {

        //
        // There're still worker threads; send one of them the axe.
        //

        ShutdownItem->QueueType = QueueType;
        ShutdownItem->PrevThread = PsGetCurrentThread();
        ObReferenceObject (ShutdownItem->PrevThread);

        KeInsertQueue (&ExWorkerQueue[QueueType].WorkerQueue,
                       &ShutdownItem->WorkItem.List);
        return TRUE;
    }

    return FALSE;               // we did not queue a shutdown
}
示例#5
0
/*
 * @implemented
 */
NTSTATUS
NTAPI
IoSetIoCompletion(IN PVOID IoCompletion,
                  IN PVOID KeyContext,
                  IN PVOID ApcContext,
                  IN NTSTATUS IoStatus,
                  IN ULONG_PTR IoStatusInformation,
                  IN BOOLEAN Quota)
{
    PKQUEUE Queue = (PKQUEUE)IoCompletion;
    PNPAGED_LOOKASIDE_LIST List;
    PKPRCB Prcb = KeGetCurrentPrcb();
    PIOP_MINI_COMPLETION_PACKET Packet;

    /* Get the P List */
    List = (PNPAGED_LOOKASIDE_LIST)Prcb->
            PPLookasideList[LookasideCompletionList].P;

    /* Try to allocate the Packet */
    List->L.TotalAllocates++;
    Packet = (PVOID)InterlockedPopEntrySList(&List->L.ListHead);

    /* Check if that failed, use the L list if it did */
    if (!Packet)
    {
        /* Let the balancer know */
        List->L.AllocateMisses++;

        /* Get L List */
        List = (PNPAGED_LOOKASIDE_LIST)Prcb->
                PPLookasideList[LookasideCompletionList].L;

        /* Try to allocate the Packet */
        List->L.TotalAllocates++;
        Packet = (PVOID)InterlockedPopEntrySList(&List->L.ListHead);
    }

    /* Still failed, use pool */
    if (!Packet)
    {
        /* Let the balancer know */
        List->L.AllocateMisses++;

        /* Allocate from Nonpaged Pool */
        Packet = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Packet), IOC_TAG);
    }

    /* Make sure we have one by now... */
    if (Packet)
    {
        /* Set up the Packet */
        Packet->PacketType = IopCompletionPacketMini;
        Packet->KeyContext = KeyContext;
        Packet->ApcContext = ApcContext;
        Packet->IoStatus = IoStatus;
        Packet->IoStatusInformation = IoStatusInformation;

        /* Insert the Queue */
        KeInsertQueue(Queue, &Packet->ListEntry);
    }
    else
    {
        /* Out of memory, fail */
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Return Success */
    return STATUS_SUCCESS;
}
示例#6
0
VOID
ExQueueWorkItem (
    __inout PWORK_QUEUE_ITEM WorkItem,
    __in WORK_QUEUE_TYPE QueueType
    )

/*++

Routine Description:

    This function inserts a work item into a work queue that is processed
    by a worker thread of the corresponding type.

Arguments:

    WorkItem - Supplies a pointer to the work item to add the the queue.
        This structure must be located in NonPagedPool. The work item
        structure contains a doubly linked list entry, the address of a
        routine to call and a parameter to pass to that routine.

    QueueType - Specifies the type of work queue that the work item
        should be placed in.

Return Value:

    None.

--*/

{
    PEX_WORK_QUEUE Queue;

    ASSERT (QueueType < MaximumWorkQueue);
    ASSERT (WorkItem->List.Flink == NULL);

    //
    // Perform a rudimentary validation on the worker routine.
    //

    if ((ULONG64)WorkItem->WorkerRoutine <= MmUserProbeAddress) {

        KeBugCheckEx (WORKER_INVALID,
                      0x1,
                      (ULONG_PTR)WorkItem,
                      (ULONG_PTR)WorkItem->WorkerRoutine,
                      0);
    }

    Queue = &ExWorkerQueue[QueueType];

    //
    // Insert the work item in the appropriate queue object.
    //

    KeInsertQueue (&Queue->WorkerQueue, &WorkItem->List);

    //
    // We check the queue's shutdown state after we insert the work
    // item to avoid the race condition when the queue's marked
    // between checking the queue and inserting the item.  It's
    // possible for the queue to be marked for shutdown between the
    // insert and this assert (so the insert would've barely sneaked
    // in), but it's not worth guarding against this -- barely
    // sneaking in is not a good design strategy, and at this point in
    // the shutdown sequence, the caller simply should not be trying
    // to insert new queue items.
    //

    ASSERT (!Queue->Info.QueueDisabled);

    //
    // Determine whether another thread should be created, and signal the
    // thread set balance manager if so.
    //

    if (ExpNewThreadNecessary (Queue) != FALSE) {
        KeSetEvent (&ExpThreadSetManagerEvent, 0, FALSE);
    }

    return;
}
示例#7
0
VOID
FsRtlpPostStackOverflow (
    IN PVOID Context,
    IN PKEVENT Event,
    IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine,
    IN BOOLEAN PagingFile
)

/*++

Routine Description:

    This routines posts a stack overflow item to the stack overflow
    thread and returns.

Arguments:

    Context - Supplies the context to pass to the stack overflow
        call back routine.  If the low order bit is set, then
        this overflow was a read to a paging file.

    Event - Supplies a pointer to an event to pass to the stack
        overflow call back routine.

    StackOverflowRoutine - Supplies the call back to use when
        processing the request in the overflow thread.

    PagingFile - Indicates if the read is destined to a paging file.

Return Value:

    None.

--*/

{
    PSTACK_OVERFLOW_ITEM StackOverflowItem;

    //
    //  Allocate a stack overflow work item it will later be deallocated by
    //  the stack overflow thread
    //

    StackOverflowItem = FsRtlAllocatePool( PagingFile ?
                                           NonPagedPoolMustSucceed :
                                           NonPagedPool,
                                           sizeof(STACK_OVERFLOW_ITEM) );

    //
    //  Fill in the fields in the new item
    //

    StackOverflowItem->Context              = Context;
    StackOverflowItem->Event                = Event;
    StackOverflowItem->StackOverflowRoutine = StackOverflowRoutine;

    ExInitializeWorkItem( &StackOverflowItem->Item,
                          &FsRtlStackOverflowRead,
                          StackOverflowItem );

    //
    //  Safely add it to the overflow queue
    //

    KeInsertQueue( &FsRtlWorkerQueues[PagingFile],
                   &StackOverflowItem->Item.List );

    //
    //  And return to our caller
    //

    return;
}
示例#8
0
VOID
FsRtlpPostStackOverflow (
    IN PVOID Context,
    IN PKEVENT Event,
    IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine,
    IN BOOLEAN PagingFile
    )

/*++

Routine Description:

    This routines posts a stack overflow item to the stack overflow
    thread and returns.

Arguments:

    Context - Supplies the context to pass to the stack overflow
        call back routine.  If the low order bit is set, then
        this overflow was a read to a paging file.

    Event - Supplies a pointer to an event to pass to the stack
        overflow call back routine.

    StackOverflowRoutine - Supplies the call back to use when
        processing the request in the overflow thread.

    PagingFile - Indicates if the read is destined to a paging file.

Return Value:

    None.

--*/

{
    PSTACK_OVERFLOW_ITEM StackOverflowItem;

    //
    //  Allocate a stack overflow work item it will later be deallocated by
    //  the stack overflow thread.  Conserve stack by raising here.
    //

    StackOverflowItem = ExAllocatePoolWithTag( NonPagedPool,
                                               sizeof(STACK_OVERFLOW_ITEM),
                                               MODULE_POOL_TAG );

    //
    //  If this fails, go to the fallback item for the paging file overflows.
    //  We can't have a single fallback item for non-pagingfile IO since this
    //  could lead to deadlocks if it waits on a thread that itself needs
    //  the fallback item.
    //
    
    if (StackOverflowItem == NULL) {
        
        if (!PagingFile) {
        
            ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
        }

        KeWaitForSingleObject( &StackOverflowFallbackSerialEvent,
                               Executive,
                               KernelMode,
                               FALSE,
                               NULL );

        StackOverflowItem = &StackOverflowFallback;
    }
    
    //
    //  Fill in the fields in the new item
    //

    StackOverflowItem->Context              = Context;
    StackOverflowItem->Event                = Event;
    StackOverflowItem->StackOverflowRoutine = StackOverflowRoutine;

    ExInitializeWorkItem( &StackOverflowItem->Item,
                          &FsRtlStackOverflowRead,
                          StackOverflowItem );

    //
    //  Safely add it to the overflow queue
    //

    KeInsertQueue( &FsRtlWorkerQueues[PagingFile],
                   &StackOverflowItem->Item.List );

    //
    //  And return to our caller
    //

    return;
}