ReactOS 0.4.15-dev-7842-g558ab78
gdipool.c File Reference
#include <win32k.h>
#include <debug.h>
Include dependency graph for gdipool.c:

Go to the source code of this file.

Classes

struct  _GDI_POOL_SECTION
 
struct  _GDI_POOL
 

Macros

#define NDEBUG
 
#define GDI_POOL_ALLOCATION_GRANULARITY   64 * 1024
 

Typedefs

typedef struct _GDI_POOL_SECTION GDI_POOL_SECTION
 
typedef struct _GDI_POOL_SECTIONPGDI_POOL_SECTION
 
typedef struct _GDI_POOL GDI_POOL
 

Functions

static PGDI_POOL_SECTION GdiPoolAllocateSection (PGDI_POOL pPool)
 
static VOID GdiPoolDeleteSection (PGDI_POOL pPool, PGDI_POOL_SECTION pSection)
 
PVOID NTAPI GdiPoolAllocate (PGDI_POOL pPool)
 
VOID NTAPI GdiPoolFree (PGDI_POOL pPool, PVOID pvAlloc)
 
PGDI_POOL NTAPI GdiPoolCreate (ULONG cjAllocSize, ULONG ulTag)
 
VOID NTAPI GdiPoolDestroy (PGDI_POOL pPool)
 

Macro Definition Documentation

◆ GDI_POOL_ALLOCATION_GRANULARITY

#define GDI_POOL_ALLOCATION_GRANULARITY   64 * 1024

Definition at line 46 of file gdipool.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file gdipool.c.

Typedef Documentation

◆ GDI_POOL

◆ GDI_POOL_SECTION

◆ PGDI_POOL_SECTION

Function Documentation

◆ GdiPoolAllocate()

PVOID NTAPI GdiPoolAllocate ( PGDI_POOL  pPool)

Definition at line 122 of file gdipool.c.

124{
125 PGDI_POOL_SECTION pSection;
126 ULONG ulIndex, cjOffset, ulPageBit;
128 PVOID pvAlloc, pvBaseAddress;
131
132 /* Disable APCs and acquire the pool lock */
135
136 /* Check if we have a ready section */
137 if (!IsListEmpty(&pPool->leReadyList))
138 {
139 /* Get a free section */
140 ple = pPool->leReadyList.Flink;
141 pSection = CONTAINING_RECORD(ple, GDI_POOL_SECTION, leReadyLink);
142 if (pSection->cAllocCount >= pPool->cSlotsPerSection)
143 {
144 DPRINT1("pSection->cAllocCount=%lu, pPool->cSlotsPerSection=%lu\n",
145 pSection->cAllocCount, pPool->cSlotsPerSection);
146 DBG_DUMP_EVENT_LIST(&pPool->slhLog);
147 ASSERT(FALSE);
148 }
149 ASSERT(pSection->cAllocCount < pPool->cSlotsPerSection);
150 }
151 else
152 {
153 /* No, check if we have something on the empty list */
154 if (!IsListEmpty(&pPool->leEmptyList))
155 {
156 /* Yes, remove it from the empty list */
157 ple = RemoveHeadList(&pPool->leEmptyList);
158 pSection = CONTAINING_RECORD(ple, GDI_POOL_SECTION, leInUseLink);
159 pPool->cEmptySections--;
160 ASSERT(pSection->cAllocCount == 0);
161 }
162 else
163 {
164 /* No, allocate a new section */
165 pSection = GdiPoolAllocateSection(pPool);
166 if (!pSection)
167 {
168 DPRINT1("Couldn't allocate a section\n");
169 pvAlloc = NULL;
170 goto done;
171 }
172 }
173
174 /* Insert it into the in-use and ready list */
175 InsertHeadList(&pPool->leInUseList, &pSection->leInUseLink);
176 InsertHeadList(&pPool->leReadyList, &pSection->leReadyLink);
177 }
178
179 /* Find and set a single bit */
180 ulIndex = RtlFindClearBitsAndSet(&pSection->bitmap, 1, 0);
181 ASSERT(ulIndex != MAXULONG);
182
183 /* Calculate the allocation address */
184 cjOffset = ulIndex * pPool->cjAllocSize;
185 pvAlloc = (PVOID)((ULONG_PTR)pSection->pvBaseAddress + cjOffset);
186
187 /* Check if memory is committed */
188 ulPageBit = 1 << (cjOffset / PAGE_SIZE);
189 ulPageBit |= 1 << ((cjOffset + pPool->cjAllocSize - 1) / PAGE_SIZE);
190 if ((pSection->ulCommitBitmap & ulPageBit) != ulPageBit)
191 {
192 /* Commit the pages */
193 pvBaseAddress = PAGE_ALIGN(pvAlloc);
195 status = ZwAllocateVirtualMemory(NtCurrentProcess(),
196 &pvBaseAddress,
197 0,
198 &cjSize,
201 if (!NT_SUCCESS(status))
202 {
203 pvAlloc = NULL;
204 goto done;
205 }
206
207 pSection->ulCommitBitmap |= ulPageBit;
208 }
209
210 /* Increase alloc count */
211 pSection->cAllocCount++;
212 ASSERT(RtlNumberOfSetBits(&pSection->bitmap) == pSection->cAllocCount);
213 DBG_LOGEVENT(&pPool->slhLog, EVENT_ALLOCATE, pvAlloc);
214
215 /* Check if section is now busy */
216 if (pSection->cAllocCount == pPool->cSlotsPerSection)
217 {
218 /* Remove the section from the ready list */
219 RemoveEntryList(&pSection->leReadyLink);
220 }
221
222done:
223 /* Release the pool lock and enable APCs */
226
227 DPRINT("GdiPoolallocate: %p\n", pvAlloc);
228 return pvAlloc;
229}
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertHeadList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1036
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1252
PSINGLE_LIST_ENTRY ple
#define DBG_LOGEVENT(pslh, type, val)
Definition: gdidebug.h:109
#define DBG_DUMP_EVENT_LIST(pslh)
Definition: gdidebug.h:111
static PGDI_POOL_SECTION GdiPoolAllocateSection(PGDI_POOL pPool)
Definition: gdipool.c:50
NTSYSAPI ULONG WINAPI RtlNumberOfSetBits(PCRTL_BITMAP)
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP, ULONG, ULONG)
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
#define ASSERT(a)
Definition: mode.c:44
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define MEM_COMMIT
Definition: nt_native.h:1313
#define DPRINT
Definition: sndvol32.h:71
ULONG cAllocCount
Definition: gdipool.c:23
LIST_ENTRY leReadyLink
Definition: gdipool.c:18
RTL_BITMAP bitmap
Definition: gdipool.c:25
ULONG ulCommitBitmap
Definition: gdipool.c:22
LIST_ENTRY leInUseLink
Definition: gdipool.c:17
PVOID pvBaseAddress
Definition: gdipool.c:20
LIST_ENTRY leInUseList
Definition: gdipool.c:41
EX_PUSH_LOCK pushlock
Definition: gdipool.c:36
ULONG cEmptySections
Definition: gdipool.c:35
ULONG cSlotsPerSection
Definition: gdipool.c:34
LIST_ENTRY leEmptyList
Definition: gdipool.c:42
ULONG cjAllocSize
Definition: gdipool.c:32
LIST_ENTRY leReadyList
Definition: gdipool.c:43
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: ps.c:97
#define MAXULONG
Definition: typedefs.h:251
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_In_ ULONG cjSize
Definition: winddi.h:3634
#define PAGE_ALIGN(Va)
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)

Referenced by BRUSH::bAllocateBrushAttr(), DC_bAllocDcAttr(), and REGION_bAllocRgnAttr().

◆ GdiPoolAllocateSection()

static PGDI_POOL_SECTION GdiPoolAllocateSection ( PGDI_POOL  pPool)
static

Definition at line 50 of file gdipool.c.

51{
52 PGDI_POOL_SECTION pSection;
53 PVOID pvBaseAddress;
56
57 /* Allocate a section object */
58 cjSize = sizeof(GDI_POOL_SECTION) + pPool->cSlotsPerSection / sizeof(ULONG);
59 pSection = EngAllocMem(0, cjSize, pPool->ulTag);
60 if (!pSection)
61 {
62 return NULL;
63 }
64
65 /* Reserve user mode memory */
67 pvBaseAddress = NULL;
68 status = ZwAllocateVirtualMemory(NtCurrentProcess(),
69 &pvBaseAddress,
70 0,
71 &cjSize,
74 if (!NT_SUCCESS(status))
75 {
76 EngFreeMem(pSection);
77 return NULL;
78 }
79
80 /* Initialize the section */
81 pSection->pvBaseAddress = pvBaseAddress;
82 pSection->ulCommitBitmap = 0;
83 pSection->cAllocCount = 0;
84 RtlInitializeBitMap(&pSection->bitmap,
85 pSection->aulBits,
86 pPool->cSlotsPerSection);
87 RtlClearAllBits(&pSection->bitmap);
88
89 /* Return the section */
90 return pSection;
91}
struct _GDI_POOL_SECTION GDI_POOL_SECTION
#define GDI_POOL_ALLOCATION_GRANULARITY
Definition: gdipool.c:46
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
NTSYSAPI void WINAPI RtlClearAllBits(PRTL_BITMAP)
#define MEM_RESERVE
Definition: nt_native.h:1314
#define EngFreeMem
Definition: polytest.cpp:56
void * EngAllocMem(int zero, unsigned long size, int tag=0)
Definition: polytest.cpp:70
ULONG aulBits[1]
Definition: gdipool.c:26
ULONG ulTag
Definition: gdipool.c:31

Referenced by GdiPoolAllocate().

◆ GdiPoolCreate()

PGDI_POOL NTAPI GdiPoolCreate ( ULONG  cjAllocSize,
ULONG  ulTag 
)

Definition at line 316 of file gdipool.c.

319{
320 PGDI_POOL pPool;
321
322 /* Allocate a pool object */
323 pPool = EngAllocMem(0, sizeof(GDI_POOL), 'lopG');
324 if (!pPool) return NULL;
325
326 /* Initialize the object */
331 pPool->cEmptySections = 0;
332 pPool->cjAllocSize = cjAllocSize;
333 pPool->ulTag = ulTag;
335 pPool->cSlotsPerSection = pPool->cjSectionSize / cjAllocSize;
336 DBG_INITLOG(&pPool->slhLog);
337
338 return pPool;
339}
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define ExInitializePushLock
Definition: ex.h:1013
#define DBG_INITLOG(pslh)
Definition: gdidebug.h:110
ULONG cjSectionSize
Definition: gdipool.c:33
_In_ ULONG _In_ ULONG ulTag
Definition: winddi.h:3942

Referenced by GdiProcessCreate().

◆ GdiPoolDeleteSection()

static VOID GdiPoolDeleteSection ( PGDI_POOL  pPool,
PGDI_POOL_SECTION  pSection 
)
static

Definition at line 95 of file gdipool.c.

96{
98 SIZE_T cjSize = 0;
99
100 /* Should not have any allocations */
101 if (pSection->cAllocCount != 0)
102 {
103 DPRINT1("There are %lu allocations left, section=%p, pool=%p\n",
104 pSection->cAllocCount, pSection, pPool);
105 DBG_DUMP_EVENT_LIST(&pPool->slhLog);
106 ASSERT(FALSE);
107 }
108
109 /* Release the virtual memory */
110 status = ZwFreeVirtualMemory(NtCurrentProcess(),
111 &pSection->pvBaseAddress,
112 &cjSize,
115
116 /* Free the section object */
117 EngFreeMem(pSection);
118}
#define MEM_RELEASE
Definition: nt_native.h:1316

Referenced by GdiPoolDestroy(), and GdiPoolFree().

◆ GdiPoolDestroy()

VOID NTAPI GdiPoolDestroy ( PGDI_POOL  pPool)

Definition at line 343 of file gdipool.c.

344{
345 PGDI_POOL_SECTION pSection;
347
348 /* Loop all empty sections, removing them */
349 while (!IsListEmpty(&pPool->leEmptyList))
350 {
351 /* Delete the section */
352 ple = RemoveHeadList(&pPool->leEmptyList);
353 pSection = CONTAINING_RECORD(ple, GDI_POOL_SECTION, leInUseLink);
354 GdiPoolDeleteSection(pPool, pSection);
355 }
356
357 /* Loop all ready sections, removing them */
358 while (!IsListEmpty(&pPool->leInUseList))
359 {
360 /* Delete the section */
361 ple = RemoveHeadList(&pPool->leInUseList);
362 pSection = CONTAINING_RECORD(ple, GDI_POOL_SECTION, leInUseLink);
363 GdiPoolDeleteSection(pPool, pSection);
364 }
365
366 DBG_CLEANUP_EVENT_LIST(&pPool->slhLog);
367
368 EngFreeMem(pPool);
369}
#define DBG_CLEANUP_EVENT_LIST(pslh)
Definition: gdidebug.h:112
static VOID GdiPoolDeleteSection(PGDI_POOL pPool, PGDI_POOL_SECTION pSection)
Definition: gdipool.c:95

Referenced by GdiProcessDestroy().

◆ GdiPoolFree()

VOID NTAPI GdiPoolFree ( PGDI_POOL  pPool,
PVOID  pvAlloc 
)

Definition at line 233 of file gdipool.c.

236{
238 PGDI_POOL_SECTION pSection = NULL;
239 ULONG_PTR cjOffset;
240 ULONG ulIndex;
241 DPRINT("GdiPoolFree: %p\n", pvAlloc);
242
243 /* Disable APCs and acquire the pool lock */
246
247 /* Loop all used sections */
248 for (ple = pPool->leInUseList.Flink;
249 ple != &pPool->leInUseList;
250 ple = ple->Flink)
251 {
252 /* Get the pointer to the section */
253 pSection = CONTAINING_RECORD(ple, GDI_POOL_SECTION, leInUseLink);
254
255 /* Calculate offset */
256 cjOffset = (ULONG_PTR)pvAlloc - (ULONG_PTR)pSection->pvBaseAddress;
257
258 /* Check if the allocation is from this section */
259 if (cjOffset < pPool->cjSectionSize)
260 {
261 /* Calculate the index of the allocation */
262 ulIndex = cjOffset / pPool->cjAllocSize;
263
264 /* Mark it as free */
265 ASSERT(RtlTestBit(&pSection->bitmap, ulIndex) == TRUE);
266 RtlClearBit(&pSection->bitmap, ulIndex);
267
268 /* Decrease allocation count */
269 pSection->cAllocCount--;
270 ASSERT(RtlNumberOfSetBits(&pSection->bitmap) == pSection->cAllocCount);
271 DBG_LOGEVENT(&pPool->slhLog, EVENT_FREE, pvAlloc);
272
273 /* Check if the section got valid now */
274 if (pSection->cAllocCount == pPool->cSlotsPerSection - 1)
275 {
276 /* Insert it into the ready list */
277 InsertTailList(&pPool->leReadyList, &pSection->leReadyLink);
278 }
279 /* Check if it got empty now */
280 else if (pSection->cAllocCount == 0)
281 {
282 /* Remove the section from the lists */
283 RemoveEntryList(&pSection->leInUseLink);
284 RemoveEntryList(&pSection->leReadyLink);
285
286 if (pPool->cEmptySections >= 1)
287 {
288 /* Delete the section */
289 GdiPoolDeleteSection(pPool, pSection);
290 }
291 else
292 {
293 /* Insert it into the empty list */
294 InsertHeadList(&pPool->leEmptyList, &pSection->leInUseLink);
295 pPool->cEmptySections++;
296 }
297 }
298
299 goto done;
300 }
301 }
302
303 DbgPrint("failed to free. pvAlloc=%p, base=%p, size=%lx\n",
304 pvAlloc, pSection ? pSection->pvBaseAddress : NULL, pPool->cjSectionSize);
305 ASSERT(FALSE);
306 // KeBugCheck()
307
308done:
309 /* Release the pool lock and enable APCs */
312}
#define TRUE
Definition: types.h:120
#define ULONG_PTR
Definition: config.h:101
#define InsertTailList(ListHead, Entry)
#define DbgPrint
Definition: hal.h:12
VOID NTAPI RtlClearBit(_In_ PRTL_BITMAP BitMapHeader, _In_ BITMAP_INDEX BitNumber)
Definition: bitmap.c:294
_Must_inspect_result_ NTSYSAPI BOOLEAN NTAPI RtlTestBit(_In_ PRTL_BITMAP BitMapHeader, _In_range_(<, BitMapHeader->SizeOfBitMap) ULONG BitNumber)
Definition: bitmap.c:434

Referenced by DC_vFreeDcAttr(), IntGdiSetRegionOwner(), REGION_vCleanup(), BRUSH::vReleaseAttribute(), and BRUSH::~BRUSH().