[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / mmsup.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/ARM3/mmsup.c
5 * PURPOSE: ARM Memory Manager Support Routines
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 #define MODULE_INVOLVED_IN_ARM3
16 #include "../ARM3/miarm.h"
17
18 /* GLOBALS ********************************************************************/
19
20 SIZE_T MmMinimumWorkingSetSize;
21 SIZE_T MmMaximumWorkingSetSize;
22 SIZE_T MmPagesAboveWsMinimum;
23
24 /* PUBLIC FUNCTIONS ***********************************************************/
25
26 /*
27 * @unimplemented
28 */
29 NTSTATUS
30 NTAPI
31 MmMapUserAddressesToPage(IN PVOID BaseAddress,
32 IN SIZE_T NumberOfBytes,
33 IN PVOID PageAddress)
34 {
35 UNIMPLEMENTED;
36 return STATUS_NOT_IMPLEMENTED;
37 }
38
39 /*
40 * @unimplemented
41 */
42 NTSTATUS
43 NTAPI
44 MmAdjustWorkingSetSize(IN SIZE_T WorkingSetMinimumInBytes,
45 IN SIZE_T WorkingSetMaximumInBytes,
46 IN ULONG SystemCache,
47 IN BOOLEAN IncreaseOkay)
48 {
49 SIZE_T MinimumWorkingSetSize, MaximumWorkingSetSize;
50 SSIZE_T Delta;
51 PMMSUPPORT Ws;
52 NTSTATUS Status;
53
54 /* Check for special case: empty the working set */
55 if ((WorkingSetMinimumInBytes == -1) &&
56 (WorkingSetMaximumInBytes == -1))
57 {
58 UNIMPLEMENTED;
59 return STATUS_NOT_IMPLEMENTED;
60 }
61
62 /* Assume success */
63 Status = STATUS_SUCCESS;
64
65 /* Get the working set and lock it */
66 Ws = &PsGetCurrentProcess()->Vm;
67 MiLockWorkingSet(PsGetCurrentThread(), Ws);
68
69 /* Calculate the actual minimum and maximum working set size to set */
70 MinimumWorkingSetSize = (WorkingSetMinimumInBytes != 0) ?
71 (WorkingSetMinimumInBytes / PAGE_SIZE) : Ws->MinimumWorkingSetSize;
72 MaximumWorkingSetSize = (WorkingSetMaximumInBytes != 0) ?
73 (WorkingSetMaximumInBytes / PAGE_SIZE) : Ws->MaximumWorkingSetSize;
74
75 /* Check if the new maximum exceeds the global maximum */
76 if (MaximumWorkingSetSize > MmMaximumWorkingSetSize)
77 {
78 MaximumWorkingSetSize = MmMaximumWorkingSetSize;
79 Status = STATUS_WORKING_SET_LIMIT_RANGE;
80 }
81
82 /* Check if the new minimum is below the global minimum */
83 if (MinimumWorkingSetSize < MmMinimumWorkingSetSize)
84 {
85 MinimumWorkingSetSize = MmMinimumWorkingSetSize;
86 Status = STATUS_WORKING_SET_LIMIT_RANGE;
87 }
88
89 /* Check if the new minimum exceeds the new maximum */
90 if (MinimumWorkingSetSize > MaximumWorkingSetSize)
91 {
92 DPRINT1("MinimumWorkingSetSize > MaximumWorkingSetSize\n");
93 Status = STATUS_BAD_WORKING_SET_LIMIT;
94 goto Cleanup;
95 }
96
97 /* Calculate the minimum WS size adjustment and check if we increase */
98 Delta = MinimumWorkingSetSize - Ws->MinimumWorkingSetSize;
99 if (Delta > 0)
100 {
101 /* Is increasing ok? */
102 if (!IncreaseOkay)
103 {
104 DPRINT1("Privilege for WS size increase not held\n");
105 Status = STATUS_PRIVILEGE_NOT_HELD;
106 goto Cleanup;
107 }
108
109 /* Check if the number of available pages is large enough */
110 if (((SIZE_T)Delta / 1024) > (MmAvailablePages - 128))
111 {
112 DPRINT1("Not enough available pages\n");
113 Status = STATUS_INSUFFICIENT_RESOURCES;
114 goto Cleanup;
115 }
116
117 /* Check if there are enough resident available pages */
118 if ((SIZE_T)Delta >
119 (MmResidentAvailablePages - MmSystemLockPagesCount - 256))
120 {
121 DPRINT1("Not enough resident pages\n");
122 Status = STATUS_INSUFFICIENT_RESOURCES;
123 goto Cleanup;
124 }
125 }
126
127 /* Update resident available pages */
128 if (Delta != 0)
129 {
130 InterlockedExchangeAddSizeT(&MmResidentAvailablePages, -Delta);
131 }
132
133 /* Calculate new pages above minimum WS size */
134 Delta += max((SSIZE_T)Ws->WorkingSetSize - MinimumWorkingSetSize, 0);
135
136 /* Subtract old pages above minimum WS size */
137 Delta -= max((SSIZE_T)Ws->WorkingSetSize - Ws->MinimumWorkingSetSize, 0);
138
139 /* If it changed, add it to the global variable */
140 if (Delta != 0)
141 {
142 InterlockedExchangeAddSizeT(&MmPagesAboveWsMinimum, Delta);
143 }
144
145 /* Set the new working set size */
146 Ws->MinimumWorkingSetSize = MinimumWorkingSetSize;
147 Ws->MaximumWorkingSetSize = MaximumWorkingSetSize;
148
149 Cleanup:
150
151 /* Unlock the working set and return the status */
152 MiUnlockWorkingSet(PsGetCurrentThread(), Ws);
153 return Status;
154 }
155
156 /*
157 * @unimplemented
158 */
159 BOOLEAN
160 NTAPI
161 MmSetAddressRangeModified(IN PVOID Address,
162 IN SIZE_T Length)
163 {
164 UNIMPLEMENTED;
165 return FALSE;
166 }
167
168 /*
169 * @implemented
170 */
171 BOOLEAN
172 NTAPI
173 MmIsAddressValid(IN PVOID VirtualAddress)
174 {
175 #if _MI_PAGING_LEVELS >= 4
176 /* Check if the PXE is valid */
177 if (MiAddressToPxe(VirtualAddress)->u.Hard.Valid == 0) return FALSE;
178 #endif
179
180 #if _MI_PAGING_LEVELS >= 3
181 /* Check if the PPE is valid */
182 if (MiAddressToPpe(VirtualAddress)->u.Hard.Valid == 0) return FALSE;
183 #endif
184
185 #if _MI_PAGING_LEVELS >= 2
186 /* Check if the PDE is valid */
187 if (MiAddressToPde(VirtualAddress)->u.Hard.Valid == 0) return FALSE;
188 #endif
189
190 /* Check if the PTE is valid */
191 if (MiAddressToPte(VirtualAddress)->u.Hard.Valid == 0) return FALSE;
192
193 /* This address is valid now, but it will only stay so if the caller holds
194 * the PFN lock */
195 return TRUE;
196 }
197
198 /*
199 * @unimplemented
200 */
201 BOOLEAN
202 NTAPI
203 MmIsNonPagedSystemAddressValid(IN PVOID VirtualAddress)
204 {
205 DPRINT1("WARNING: %s returns bogus result\n", __FUNCTION__);
206 return MmIsAddressValid(VirtualAddress);
207 }
208
209 /*
210 * @unimplemented
211 */
212 NTSTATUS
213 NTAPI
214 MmSetBankedSection(IN HANDLE ProcessHandle,
215 IN PVOID VirtualAddress,
216 IN ULONG BankLength,
217 IN BOOLEAN ReadWriteBank,
218 IN PVOID BankRoutine,
219 IN PVOID Context)
220 {
221 UNIMPLEMENTED;
222 return STATUS_NOT_IMPLEMENTED;
223 }
224
225 /*
226 * @implemented
227 */
228 BOOLEAN
229 NTAPI
230 MmIsRecursiveIoFault(VOID)
231 {
232 PETHREAD Thread = PsGetCurrentThread();
233
234 //
235 // If any of these is true, this is a recursive fault
236 //
237 return ((Thread->DisablePageFaultClustering) | (Thread->ForwardClusterOnly));
238 }
239
240 /*
241 * @implemented
242 */
243 BOOLEAN
244 NTAPI
245 MmIsThisAnNtAsSystem(VOID)
246 {
247 /* Return if this is a server system */
248 return MmProductType & 0xFF;
249 }
250
251 /*
252 * @implemented
253 */
254 MM_SYSTEMSIZE
255 NTAPI
256 MmQuerySystemSize(VOID)
257 {
258 /* Return the low, medium or high memory system type */
259 return MmSystemSize;
260 }
261
262 /* EOF */