3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: balance.c,v 1.1 2001/12/28 00:04:45 dwelch Exp $
21 * COPYRIGHT: See COPYING in the top directory
22 * PROJECT: ReactOS kernel
23 * FILE: ntoskrnl/mm/balance.c
24 * PURPOSE: kernel memory managment functions
25 * PROGRAMMER: David Welch (welch@cwcom.net)
30 /* INCLUDES *****************************************************************/
32 #include <ddk/ntddk.h>
33 #include <internal/mm.h>
36 #include <internal/debug.h>
38 /* TYPES ********************************************************************/
40 typedef struct _MM_MEMORY_CONSUMER
44 NTSTATUS (*Trim
)(ULONG Target
, ULONG Priority
, PULONG NrFreed
, PVOID
* FreedPages
);
45 } MM_MEMORY_CONSUMER
, *PMM_MEMORY_CONSUMER
;
51 #define MC_MAXIMUM (4)
53 /* GLOBALS ******************************************************************/
55 static MM_MEMORY_CONSUMER MiMemoryConsumers
[MC_MAXIMUM
];
56 static ULONG MiMinimumAvailablePages
;
57 static ULONG MiNrAvailablePages
;
58 static ULONG MiNrTotalPages
;
60 /* FUNCTIONS ****************************************************************/
63 MmInitializeBalancer(ULONG NrAvailablePages
)
65 memset(MiMemoryConsumers
, 0, sizeof(MiMemoryConsumers
));
67 MiNrAvailablePages
= MiNrTotalPages
= NrAvailablePages
;
70 MiMinimumAvailablePages
= 64;
71 MiMemoryConsumers
[MC_CACHE
].PagesTarget
= NrAvailablePages
/ 2;
72 MiMemoryConsumers
[MC_USER
].PagesTarget
= NrAvailablePages
- MiMinimumAvailablePages
;
73 MiMemoryConsumers
[MC_PPOOL
].PagesTarget
= NrAvailablePages
/ 2;
74 MiMemoryConsumers
[MC_NPPOOL
].PagesTarget
= 0xFFFFFFFF;
78 MmInitializeMemoryConsumer(ULONG Consumer
,
79 NTSTATUS (*Trim
)(ULONG Target
, ULONG Priority
,
80 PULONG NrFreed
, PVOID
* FreedPages
))
82 MiMemoryConsumers
[Consumer
].Trim
= Trim
;
86 MmReleasePageMemoryConsumer(ULONG Consumer
, PVOID Page
)
88 InterlockedDecrement(&MiMemoryConsumers
[Consumer
].PagesUsed
);
89 InterlockedIncrement(&MiNrAvailablePages
);
90 MmDereferencePage(Page
);
91 return(STATUS_SUCCESS
);
95 MiTrimMemoryConsumer(ULONG Consumer
)
99 Target
= MiMemoryConsumers
[Consumer
].PagesUsed
- MiMemoryConsumers
[Consumer
].PagesTarget
;
105 if (MiMemoryConsumers
[Consumer
].Trim
!= NULL
)
107 MiMemoryConsumers
[Consumer
].Trim(Target
, 0, NULL
, NULL
);
112 MiRebalanceMemoryConsumers(PVOID
* Page
)
118 ULONG TotalFreedPages
;
120 Target
= MiMinimumAvailablePages
- MiNrAvailablePages
;
126 FreedPages
= alloca(sizeof(PVOID
) * Target
);
129 for (i
= 0; i
< MC_MAXIMUM
&& Target
> 0; i
++)
131 if (MiMemoryConsumers
[i
].Trim
!= NULL
)
133 MiMemoryConsumers
[i
].Trim(Target
, 0, &NrFreedPages
, FreedPages
);
134 Target
= Target
- NrFreedPages
;
135 FreedPages
= FreedPages
+ NrFreedPages
;
136 TotalFreedPages
= TotalFreedPages
+ NrFreedPages
;
145 *Page
= FreedPages
[0];
152 for (; i
< TotalFreedPages
; i
++)
154 MmDereferencePage(FreedPages
[i
]);
159 MmRequestPageMemoryConsumer(ULONG Consumer
, BOOLEAN CanWait
, PVOID
* AllocatedPage
)
166 * Make sure we don't exceed our individual target.
168 OldUsed
= InterlockedIncrement(&MiMemoryConsumers
[Consumer
].PagesUsed
);
169 if (OldUsed
>= (MiMemoryConsumers
[Consumer
].PagesTarget
- 1))
173 InterlockedDecrement(&MiMemoryConsumers
[Consumer
].PagesUsed
);
174 return(STATUS_NO_MEMORY
);
176 MiTrimMemoryConsumer(Consumer
);
180 * Make sure we don't exceed global targets.
182 OldAvailable
= InterlockedDecrement(&MiNrAvailablePages
);
183 if (OldAvailable
< MiMinimumAvailablePages
)
187 InterlockedIncrement(&MiNrAvailablePages
);
188 InterlockedDecrement(&MiMemoryConsumers
[Consumer
].PagesUsed
);
189 return(STATUS_NO_MEMORY
);
191 MiRebalanceMemoryConsumers(NULL
);
195 * Actually allocate the page.
197 Page
= MmAllocPage(0);
200 /* Still not trimmed enough. */
203 InterlockedIncrement(&MiNrAvailablePages
);
204 InterlockedDecrement(&MiMemoryConsumers
[Consumer
].PagesUsed
);
205 return(STATUS_NO_MEMORY
);
207 MiRebalanceMemoryConsumers(&Page
);
209 *AllocatedPage
= Page
;
211 return(STATUS_SUCCESS
);