/*++ * @name ExpCheckDynamicThreadCount * * The ExpCheckDynamicThreadCount routine checks every queue and creates a * dynamic thread if the queue seems to be deadlocked. * * @param None * * @return None. * * @remarks The algorithm for deciding if a new thread must be created is * based on wether the queue has processed no new items in the last * second, and new items are still enqueued. * *--*/ VOID NTAPI ExpDetectWorkerThreadDeadlock(VOID) { ULONG i; PEX_WORK_QUEUE Queue; /* Loop the 3 queues */ for (i = 0; i < MaximumWorkQueue; i++) { /* Get the queue */ Queue = &ExWorkerQueue[i]; ASSERT(Queue->DynamicThreadCount <= 16); /* Check if stuff is on the queue that still is unprocessed */ if ((Queue->QueueDepthLastPass) && (Queue->WorkItemsProcessed == Queue->WorkItemsProcessedLastPass) && (Queue->DynamicThreadCount < 16)) { /* Stuff is still on the queue and nobody did anything about it */ DPRINT1("EX: Work Queue Deadlock detected: %d\n", i); ExpCreateWorkerThread(i, TRUE); DPRINT1("Dynamic threads queued %d\n", Queue->DynamicThreadCount); } /* Update our data */ Queue->WorkItemsProcessedLastPass = Queue->WorkItemsProcessed; Queue->QueueDepthLastPass = KeReadStateQueue(&Queue->WorkerQueue); } }
VOID ExpDetectWorkerThreadDeadlock ( VOID ) /*++ Routine Description: This function creates new work item threads if a possible deadlock is detected. Arguments: None. Return Value: None --*/ { ULONG Index; PEX_WORK_QUEUE Queue; PAGED_CODE(); // // Process each queue type. // for (Index = 0; Index < MaximumWorkQueue; Index += 1) { Queue = &ExWorkerQueue[Index]; ASSERT( Queue->DynamicThreadCount <= MAX_ADDITIONAL_DYNAMIC_THREADS ); if ((Queue->QueueDepthLastPass > 0) && (Queue->WorkItemsProcessed == Queue->WorkItemsProcessedLastPass) && (Queue->DynamicThreadCount < MAX_ADDITIONAL_DYNAMIC_THREADS)) { // // These things are known: // // - There were work items waiting in the queue at the last pass. // - No work items have been processed since the last pass. // - We haven't yet created the maximum number of dynamic threads. // // Things look like they're stuck, create a new thread for this // queue. // // We explicitly ignore an error from ExpCreateDynamicThread(): // we'll try again in another detection period if the queue looks // like it's still stuck. // ExpCreateWorkerThread (Index, TRUE); } // // Update some bookkeeping. // // Note that WorkItemsProcessed and the queue depth must be recorded // in that order to avoid getting a false deadlock indication. // Queue->WorkItemsProcessedLastPass = Queue->WorkItemsProcessed; Queue->QueueDepthLastPass = KeReadStateQueue (&Queue->WorkerQueue); } }