2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/balmgr.c
5 * PURPOSE: Balance Set Manager
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 #define THREAD_BOOST_PRIORITY (LOW_REALTIME_PRIORITY - 1)
18 ULONG KiReadyScanLast
;
20 /* PRIVATE FUNCTIONS *********************************************************/
24 KiScanReadyQueues(IN PKDPC Dpc
,
25 IN PVOID DeferredContext
,
26 IN PVOID SystemArgument1
,
27 IN PVOID SystemArgument2
)
29 PULONG ScanLast
= DeferredContext
;
30 ULONG ScanIndex
= *ScanLast
;
31 ULONG Count
= 10, Number
= 16;
32 PKPRCB Prcb
= KiProcessorBlock
[ScanIndex
];
33 ULONG Index
= Prcb
->QueueIndex
;
34 ULONG WaitLimit
= KeTickCount
.LowPart
- 300;
37 PLIST_ENTRY ListHead
, NextEntry
;
40 /* Lock the dispatcher and PRCB */
41 OldIrql
= KiAcquireDispatcherLock();
42 KiAcquirePrcbLock(Prcb
);
43 /* Check if there's any thread that need help */
44 Summary
= Prcb
->ReadySummary
& ((1 << THREAD_BOOST_PRIORITY
) - 2);
50 /* Normalize the index */
51 if (Index
> (THREAD_BOOST_PRIORITY
- 1)) Index
= 1;
53 /* Loop for ready threads */
54 if (Summary
& PRIORITY_MASK(Index
))
57 ASSERT(!IsListEmpty(&Prcb
->DispatcherReadyListHead
[Index
]));
59 /* Update summary and select list */
60 Summary
^= PRIORITY_MASK(Index
);
61 ListHead
= &Prcb
->DispatcherReadyListHead
[Index
];
62 NextEntry
= ListHead
->Flink
;
66 Thread
= CONTAINING_RECORD(NextEntry
,
69 ASSERT(Thread
->Priority
== Index
);
71 /* Check if the thread has been waiting too long */
72 if (WaitLimit
>= Thread
->WaitTime
)
74 /* Remove the thread from the queue */
75 NextEntry
= NextEntry
->Blink
;
76 ASSERT((Prcb
->ReadySummary
& PRIORITY_MASK(Index
)));
77 if (RemoveEntryList(NextEntry
->Flink
))
79 /* The list is empty now */
80 Prcb
->ReadySummary
^= PRIORITY_MASK(Index
);
83 /* Verify priority decrement and set the new one */
84 ASSERT((Thread
->PriorityDecrement
>= 0) &&
85 (Thread
->PriorityDecrement
<=
87 Thread
->PriorityDecrement
+= (THREAD_BOOST_PRIORITY
-
89 ASSERT((Thread
->PriorityDecrement
>= 0) &&
90 (Thread
->PriorityDecrement
<=
91 THREAD_BOOST_PRIORITY
));
93 /* Update priority and insert into ready list */
94 Thread
->Priority
= THREAD_BOOST_PRIORITY
;
95 Thread
->Quantum
= WAIT_QUANTUM_DECREMENT
* 4;
96 KiInsertDeferredReadyList(Thread
);
100 /* Go to the next entry */
101 NextEntry
= NextEntry
->Flink
;
103 } while((NextEntry
!= ListHead
) && (Number
) && (Count
));
108 } while ((Summary
) && (Number
) && (Count
));
111 /* Release the locks and dispatcher */
112 KiReleasePrcbLock(Prcb
);
113 KiReleaseDispatcherLock(OldIrql
);
115 /* Update the queue index for next time */
116 if ((Count
) && (Number
))
118 /* Reset the queue at index 1 */
119 Prcb
->QueueIndex
= 1;
123 /* Set the index we're in now */
124 Prcb
->QueueIndex
= Index
;
127 /* Increment the CPU number for next time and normalize to CPU count */
129 if (ScanIndex
== KeNumberProcessors
) ScanIndex
= 0;
131 /* Return the index */
132 *ScanLast
= ScanIndex
;
137 KeBalanceSetManager(IN PVOID Context
)
141 LARGE_INTEGER DueTime
;
142 KWAIT_BLOCK WaitBlockArray
[1];
143 PVOID WaitObjects
[1];
146 /* Set us at a low real-time priority level */
147 KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY
);
149 /* Setup the timer and scanner DPC */
150 KeInitializeTimerEx(&PeriodTimer
, SynchronizationTimer
);
151 KeInitializeDpc(&ScanDpc
, KiScanReadyQueues
, &KiReadyScanLast
);
153 /* Setup the periodic timer */
154 DueTime
.QuadPart
= -1 * 10 * 1000 * 1000;
155 KeSetTimerEx(&PeriodTimer
, DueTime
, 1000, &ScanDpc
);
157 /* Setup the wait objects */
158 WaitObjects
[0] = &PeriodTimer
;
159 //WaitObjects[1] = MmWorkingSetManagerEvent; // NO WS Management Yet!
161 /* Start wait loop */
164 /* Wait on our objects */
165 Status
= KeWaitForMultipleObjects(1,
175 /* Check if our timer expired */
178 /* Adjust lookaside lists */
179 //ExAdjustLookasideDepth();
181 /* Call the working set manager */
182 //MmWorkingSetManager();
184 /* FIXME: Outswap stacks */
189 /* Check if the working set manager notified us */
192 /* Call the working set manager */
193 //MmWorkingSetManager();
198 DPRINT1("BALMGR: Illegal wait status, %lx =\n", Status
);