Skip to content
Navigation Menu
{{ message }}
forked from erwinwang/HelloX_Kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHEAP.C
More file actions
644 lines (582 loc) · 21.2 KB
/
Copy pathHEAP.C
File metadata and controls
644 lines (582 loc) · 21.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
//***********************************************************************/
// Author : Garry
// Original Date : May,20 2006
// Module Name : HEAP.CPP
// Module Funciton :
// This module countains Heap's implementation code.
// Last modified Author :
// Last modified Date :
// Last modified Content :
// 1.
// 2.
// Lines number :
//***********************************************************************/
#ifndef __STDAFX_H__
#include "StdAfx.h"
#endif
//If and only if the VMM function is enabled,heap function is available since
//it's reley on the VMM mechanism.
#ifdef __CFG_SYS_VMM
//#ifndef __HEAP_H__
//#include "HEAP.H"
//#endif
//
//The implementation of CreateHeap routine.
//This routine does the following:
// 1. Allocate a virtual area according to dwInitSize;
// 3. Create a virtual area node object,to manage the virtual area;
// 2. Create a heap object,and initialize it;
// 4. Insert the virtual area node into heap's virtual area node list;
// 5. Insert the virtual area into heap object's free list;
// 6. Insert the heap object into kernel thread's list;
// 7. If all successful,return the help object's base address.
//
static __HEAP_OBJECT* CreateHeap(DWORD dwInitSize)
{
__HEAP_OBJECT* lpHeapObject = NULL;
__HEAP_OBJECT* lpHeapRoot = NULL;
__VIRTUAL_AREA_NODE* lpVirtualArea = NULL;
__FREE_BLOCK_HEADER* lpFreeHeader = NULL;
LPVOID lpVirtualAddr = NULL;
BOOL bResult = FALSE;
DWORD dwFlags = 0;
if(dwInitSize > MAX_VIRTUAL_AREA_SIZE) //Requested size too big.
return NULL;
if(dwInitSize < DEFAULT_VIRTUAL_AREA_SIZE)
dwInitSize = DEFAULT_VIRTUAL_AREA_SIZE;
//
//Now,allocate the virtual area.
//
lpVirtualAddr = GET_VIRTUAL_AREA(dwInitSize);
if(NULL == lpVirtualAddr) //Can not get virtual area.
goto __TERMINAL;
lpFreeHeader = (__FREE_BLOCK_HEADER*)lpVirtualAddr;
lpFreeHeader->dwFlags = BLOCK_FLAGS_FREE;
lpFreeHeader->dwBlockSize = dwInitSize - sizeof(__FREE_BLOCK_HEADER); //Caution!!!
//
//Now,create a virtual area node object,to manage virtual area.
//
lpVirtualArea = (__VIRTUAL_AREA_NODE*)GET_KERNEL_MEMORY(
sizeof(__VIRTUAL_AREA_NODE));
if(NULL == lpVirtualArea) //Can not get memory.
goto __TERMINAL;
lpVirtualArea->lpStartAddress = lpVirtualAddr;
lpVirtualArea->dwAreaSize = dwInitSize;
lpVirtualArea->lpNext = NULL;
//
//Now,create a heap object,and initialize it.
//
lpHeapObject = (__HEAP_OBJECT*)GET_KERNEL_MEMORY(sizeof(__HEAP_OBJECT));
if(NULL == lpHeapObject) //Can not allocate memory.
goto __TERMINAL;
lpHeapObject->lpVirtualArea = lpVirtualArea; //Virtual area node list.
lpHeapObject->FreeBlockHeader.dwFlags |= BLOCK_FLAGS_FREE;
lpHeapObject->FreeBlockHeader.dwFlags &= ~BLOCK_FLAGS_USED;
lpHeapObject->FreeBlockHeader.dwBlockSize = 0;
lpHeapObject->lpPrev = lpHeapObject; //Pointing to itself.
lpHeapObject->lpNext = lpHeapObject; //Pointing to itself.
__ENTER_CRITICAL_SECTION(NULL,dwFlags); //Critical section here.
lpHeapObject->lpKernelThread = CURRENT_KERNEL_THREAD;
lpHeapRoot = (__HEAP_OBJECT*)CURRENT_KERNEL_THREAD->lpHeapObject;
if(NULL == lpHeapRoot) //Has not any heap yet.
{
CURRENT_KERNEL_THREAD->lpHeapObject = (LPVOID)lpHeapObject;
}
else //Has at least one heap object,so insert it into the list.
{
lpHeapObject->lpPrev = lpHeapRoot->lpPrev;
lpHeapObject->lpNext = lpHeapRoot;
lpHeapObject->lpNext->lpPrev = lpHeapObject;
lpHeapObject->lpPrev->lpNext = lpHeapObject;
}
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
//
//Now,add the virtual area into the heap object's free list.
//
lpFreeHeader->lpPrev = &(lpHeapObject->FreeBlockHeader);
lpFreeHeader->lpNext = &(lpHeapObject->FreeBlockHeader);
lpHeapObject->FreeBlockHeader.lpPrev = lpFreeHeader;
lpHeapObject->FreeBlockHeader.lpNext = lpFreeHeader;
bResult = TRUE; //The whole operation is successful.
__TERMINAL:
if(!bResult) //Failed.
{
if(lpVirtualAddr) //Should release it.
RELEASE_VIRTUAL_AREA(lpVirtualAddr);
if(lpHeapObject)
RELEASE_KERNEL_MEMORY((LPVOID)lpHeapObject);
if(lpVirtualArea)
RELEASE_KERNEL_MEMORY((LPVOID)lpVirtualArea);
lpHeapObject = NULL; //Should return a NULL flags.
}
return lpHeapObject;
}
//
//The implementation of DestroyHeap routine.
//This routine does the following:
// 1. Delete the heap object from kernel thread's heap list;
// 2. Release all virtual areas belong to this heap;
// 3. Release the virtual area list;
// 4. Release the heap object itself.
//
static VOID DestroyHeap(__HEAP_OBJECT* lpHeapObject)
{
__VIRTUAL_AREA_NODE* lpVirtualArea = NULL;
__VIRTUAL_AREA_NODE* lpVirtualTmp = NULL;
//LPVOID lpVirtualAddr = NULL;
DWORD dwFlags = 0;
if(NULL == lpHeapObject) //Parameter check.
{
return;
}
if(lpHeapObject == lpHeapObject->lpNext) //Only one heap object in current thread.
{
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
lpHeapObject->lpKernelThread->lpHeapObject = NULL;
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
}
else //Delete itself from the kernel thread's heap list.
{
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
if(lpHeapObject->lpKernelThread->lpHeapObject == lpHeapObject)
{
lpHeapObject->lpKernelThread->lpHeapObject = (LPVOID)lpHeapObject->lpNext;
}
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
lpHeapObject->lpPrev->lpNext = lpHeapObject->lpNext;
lpHeapObject->lpNext->lpPrev = lpHeapObject->lpPrev;
}
lpVirtualArea = lpHeapObject->lpVirtualArea;
while(lpVirtualArea)
{
lpVirtualTmp = lpVirtualArea;
lpVirtualArea = lpVirtualArea->lpNext;
RELEASE_VIRTUAL_AREA(lpVirtualTmp->lpStartAddress); //Release the virtual area.
RELEASE_KERNEL_MEMORY((LPVOID)lpVirtualTmp);
}
//
//Now,should release the heap object itself.
//
RELEASE_KERNEL_MEMORY((LPVOID)lpHeapObject);
return;
}
//
//DestroyAllHeap's implementation.
//This routine destroys all heaps of the current kernel thread.
//
static VOID DestroyAllHeap(void)
{
__HEAP_OBJECT* lpHeapObj1 = NULL;
__HEAP_OBJECT* lpHeapObj2 = NULL;
__HEAP_OBJECT* lpHeapRoot = NULL;
lpHeapRoot = (__HEAP_OBJECT*)CURRENT_KERNEL_THREAD->lpHeapObject;
if(NULL == lpHeapRoot) //Not any heap object.
return;
lpHeapObj1 = lpHeapRoot->lpNext;
while(lpHeapRoot != lpHeapObj1)
{
lpHeapObj2 = lpHeapObj1->lpNext;
DestroyHeap(lpHeapObj1);
lpHeapObj1 = lpHeapObj2;
}
DestroyHeap(lpHeapRoot); //Destroy the root heap.
}
//
//The following is a help routine,used to print out the heap information of
//a kernel thread.
//
VOID PrintHeapInfo(__KERNEL_THREAD_OBJECT* lpKernelThread)
{
__HEAP_OBJECT* lpHeapObject = NULL;
__HEAP_OBJECT* lpHeapTmp = NULL;
DWORD dwFlags = 0;
__VIRTUAL_AREA_NODE* lpVirtualArea = NULL;
if(NULL == lpKernelThread) //Parameter check.
return;
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
lpHeapObject = (__HEAP_OBJECT*)lpKernelThread->lpHeapObject;
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
//printf("Start to print out the heap information.\r\n");
lpHeapTmp = lpHeapObject;
while(lpHeapTmp)
{
//printf("Begin a heap.......\r\n");
lpVirtualArea = lpHeapTmp->lpVirtualArea;
while(lpVirtualArea)
{
//printf("Start address is : %X\r\n",lpVirtualArea->lpStartAddress);
lpVirtualArea = lpVirtualArea->lpNext;
}
lpHeapTmp = lpHeapTmp->lpNext;
if(lpHeapObject == lpHeapTmp) //The same heap object.
break;
}
}
//
//The following routine is a help routine,used to dumpout the free block list.
//
VOID DumpFreeList(__HEAP_OBJECT* lpHeapObj)
{
__FREE_BLOCK_HEADER * lpFreeHeader = NULL;
if(NULL == lpHeapObj) //Invalid parameter
return;
//printf("\r\nBegin to dump out the free list:\r\n");
lpFreeHeader = lpHeapObj->FreeBlockHeader.lpNext;
while(lpFreeHeader != &lpHeapObj->FreeBlockHeader)
{
//printf("StartAddr: 0x%8X Size: %d\r\n",
// (DWORD)lpFreeHeader + sizeof(__FREE_BLOCK_HEADER),
// lpFreeHeader->dwBlockSize);
lpFreeHeader = lpFreeHeader->lpNext;
}
}
//
//The implementation of HeapAlloc routine.
//This routine does the following actions:
// 1. Check if the heap object given by user belong to current kernel thread,
// that is,only the thread that heap object belong to can allocate memory
// from it;
// 2. Check the free list of the heap,try to find a free block can statisfy
// user's request;
// 3. If can find the block,then split the block in case of the block size is
// big,and return one to user,or return the whole block to user in case of
// the block is not too big;
// 4. If can not find the block,then allocate a virtual area according to user's
// request,and split the virtual area,one part returned to user,insert another
// part into free list;
// 5. If any failure,returns NULL to indicate failed.
//
static LPVOID HeapAlloc(__HEAP_OBJECT* lpHeapObject,DWORD dwSize)
{
__VIRTUAL_AREA_NODE* lpVirtualArea = NULL;
__FREE_BLOCK_HEADER* lpFreeBlock = NULL;
__FREE_BLOCK_HEADER* lpTmpHeader = NULL;
LPVOID lpResult = NULL;
DWORD dwFlags = 0;
DWORD dwFindSize = 0;
if((NULL == lpHeapObject) || (0 == dwSize)) //Parameter check.
return lpResult;
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
if(lpHeapObject->lpKernelThread != CURRENT_KERNEL_THREAD) //Check the heap's owner.
{
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return lpResult;
}
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
if(dwSize < MIN_BLOCK_SIZE)
dwSize = MIN_BLOCK_SIZE;
dwFindSize = dwSize + MIN_BLOCK_SIZE + sizeof(__FREE_BLOCK_HEADER);
//
//Now,check the free list,try to find a free block.
//
lpFreeBlock = lpHeapObject->FreeBlockHeader.lpNext;
while(lpFreeBlock != &lpHeapObject->FreeBlockHeader)
{
if(lpFreeBlock->dwBlockSize >= dwSize) //Find one.
{
if(lpFreeBlock->dwBlockSize >= dwFindSize) //Should split it into two free blocks.
{
lpTmpHeader = (__FREE_BLOCK_HEADER*)((DWORD)lpFreeBlock + dwSize
+ sizeof(__FREE_BLOCK_HEADER)); //Pointing to second part.
lpTmpHeader->dwFlags = BLOCK_FLAGS_FREE;
lpTmpHeader->dwBlockSize = lpFreeBlock->dwBlockSize - dwSize
- sizeof(__FREE_BLOCK_HEADER); //Calculate second part's size.
//
//Now,should replace the lpFreeBlock with lpTmpHeader.
//
lpTmpHeader->lpNext = lpFreeBlock->lpNext;
lpTmpHeader->lpPrev = lpFreeBlock->lpPrev;
lpTmpHeader->lpNext->lpPrev = lpTmpHeader;
lpTmpHeader->lpPrev->lpNext = lpTmpHeader;
lpFreeBlock->dwBlockSize = dwSize;
lpFreeBlock->dwFlags |= BLOCK_FLAGS_USED;
lpFreeBlock->dwFlags &= ~BLOCK_FLAGS_FREE; //Clear the free flags.
lpFreeBlock->lpPrev = NULL;
lpFreeBlock->lpNext = NULL;
lpResult = (LPVOID)((DWORD)lpFreeBlock
+ sizeof(__FREE_BLOCK_HEADER));
goto __TERMINAL;
}
else //Now need to split,return the block is OK.
{
//
//Delete the free block from free block list.
//
lpFreeBlock->lpNext->lpPrev = lpFreeBlock->lpPrev;
lpFreeBlock->lpPrev->lpNext = lpFreeBlock->lpNext;
lpFreeBlock->dwFlags |= BLOCK_FLAGS_USED;
lpFreeBlock->dwFlags &= ~BLOCK_FLAGS_FREE; //Clear free bit.
lpFreeBlock->lpNext = NULL;
lpFreeBlock->lpPrev = NULL;
lpResult = (LPVOID)((DWORD)lpFreeBlock + sizeof(__FREE_BLOCK_HEADER));
goto __TERMINAL;
}
}
lpFreeBlock = lpFreeBlock->lpNext; //Check the next block.
}
if(lpResult) //Have found a block.
goto __TERMINAL;
//
//If can not find a statisfying block in above process,we should allocate a
//new virtual area according to dwSize,insert the virtual area into free list,
//then repeat above process.
//
lpVirtualArea = (__VIRTUAL_AREA_NODE*)GET_KERNEL_MEMORY(sizeof(__VIRTUAL_AREA_NODE));
if(NULL == lpVirtualArea) //Can not allocate kernel memory.
goto __TERMINAL;
lpVirtualArea->dwAreaSize = ((dwSize + sizeof(__FREE_BLOCK_HEADER))
> DEFAULT_VIRTUAL_AREA_SIZE) ?
(dwSize + sizeof(__FREE_BLOCK_HEADER)) : DEFAULT_VIRTUAL_AREA_SIZE;
lpVirtualArea->lpStartAddress = GET_VIRTUAL_AREA(lpVirtualArea->dwAreaSize);
if(NULL == lpVirtualArea->lpStartAddress) //Can not get virtual area.
{
RELEASE_KERNEL_MEMORY((LPVOID)lpVirtualArea);
goto __TERMINAL;
}
//
//Insert the virtual area node object into virtual area list
//of current heap object.
//
lpVirtualArea->lpNext = lpHeapObject->lpVirtualArea;
lpHeapObject->lpVirtualArea = lpVirtualArea;
//
//Now,insert the free block(virtual area) into free list of the
//heap object.
//
lpTmpHeader = (__FREE_BLOCK_HEADER*)lpVirtualArea->lpStartAddress;
lpTmpHeader->dwFlags |= BLOCK_FLAGS_FREE;
lpTmpHeader->dwFlags &= ~BLOCK_FLAGS_USED; //Clear the used flags.
lpTmpHeader->dwBlockSize = lpVirtualArea->dwAreaSize - sizeof(__FREE_BLOCK_HEADER);
lpTmpHeader->lpNext = lpHeapObject->FreeBlockHeader.lpNext;
lpTmpHeader->lpPrev = &lpHeapObject->FreeBlockHeader;
lpTmpHeader->lpNext->lpPrev = lpTmpHeader;
lpTmpHeader->lpPrev->lpNext = lpTmpHeader;
//
//Now,call HeapAlloc again,this time must successful.
//
lpResult = HeapAlloc(lpHeapObject,dwSize);
__TERMINAL:
return lpResult;
}
//
//The following routine is a helper routine,used to combine several small
//free blocks into one big free block.
//The combine unit is a virtual area,so,a problem may exists:if two virtual
//areas,one's end address is the same as the other's start address,so in normal
//case,these two virtual area should be combined into one big block.But in
//current implementation,this function is implemented by Hello China,in fact,
//this function have very seldom influence the efficiency.
//This routine does the following actions:
// 1. From the first block,check if there are at least two blocks free and
// consecutive;
// 2. If so,combine the two blocks into one block,and remove one from free
// list;
// 3. Until reach the end position of the virtual area.
//
static VOID CombineBlock(__VIRTUAL_AREA_NODE* lpVirtualArea,__HEAP_OBJECT* lpHeapObj)
{
__FREE_BLOCK_HEADER* lpFirstBlock = NULL;
__FREE_BLOCK_HEADER* lpSecondBlock = NULL;
LPVOID lpEndAddr = NULL;
if((NULL == lpVirtualArea) || (NULL == lpHeapObj)) //Invalid parameters.
return;
lpEndAddr = (LPVOID)((DWORD)lpVirtualArea->lpStartAddress
+ lpVirtualArea->dwAreaSize);
lpFirstBlock = (__FREE_BLOCK_HEADER*)lpVirtualArea->lpStartAddress;
lpSecondBlock = (__FREE_BLOCK_HEADER*)((DWORD)lpFirstBlock
+ sizeof(__FREE_BLOCK_HEADER)
+ lpFirstBlock->dwBlockSize); //Now,lpSecondBlock pointing to the second block.
while(TRUE)
{
if(lpEndAddr == (LPVOID)lpSecondBlock) //Reach the end of the virtual area.
break;
if((lpFirstBlock->dwFlags & BLOCK_FLAGS_FREE) &&
(lpSecondBlock->dwFlags & BLOCK_FLAGS_FREE)) //Two blocks all free,combine it.
{
lpFirstBlock->dwBlockSize += lpSecondBlock->dwBlockSize;
lpFirstBlock->dwBlockSize += sizeof(__FREE_BLOCK_HEADER);
//
//Delete the second block from free list.
//
lpSecondBlock->lpNext->lpPrev = lpSecondBlock->lpPrev;
lpSecondBlock->lpPrev->lpNext = lpSecondBlock->lpNext;
lpSecondBlock = (__FREE_BLOCK_HEADER*)((DWORD)lpFirstBlock
+ sizeof(__FREE_BLOCK_HEADER)
+ lpFirstBlock->dwBlockSize); //Update the second block.
continue; //Continue to next round.
}
if((lpFirstBlock->dwFlags & BLOCK_FLAGS_USED) ||
(lpSecondBlock->dwFlags & BLOCK_FLAGS_USED)) //Any block is used.
{
lpFirstBlock = lpSecondBlock;
lpSecondBlock = (__FREE_BLOCK_HEADER*)((DWORD)lpFirstBlock
+ sizeof(__FREE_BLOCK_HEADER)
+ lpFirstBlock->dwBlockSize);
continue;
}
}
}
//
//The implementation of HeapFree routine.
//This routine does the following:
// 1. Insert the memory block freed by user into heap's free list;
// 2. Find which virtual area this address belong to;
// 3. Combine the virtual area by calling CombineBlock routine;
// 4. Check if the virtual area to be combined is ONE free block,
// If so,then release the virtual area and virtual area node
// object.
//
static VOID HeapFree(LPVOID lpStartAddr,__HEAP_OBJECT* lpHeapObj)
{
__FREE_BLOCK_HEADER* lpFreeHeader = NULL;
__VIRTUAL_AREA_NODE* lpVirtualArea = NULL;
__VIRTUAL_AREA_NODE* lpVirtualTmp = NULL;
if((NULL == lpStartAddr) || (NULL == lpHeapObj)) //Invalid parameter.
return;
lpFreeHeader = (__FREE_BLOCK_HEADER*)((DWORD)lpStartAddr
- sizeof(__FREE_BLOCK_HEADER)); //Get the block's header.
if(!(lpFreeHeader->dwFlags & BLOCK_FLAGS_USED)) //Abnormal case.
return;
//
//Now,check the block to be freed belong to which virtual area.
//
lpVirtualArea = lpHeapObj->lpVirtualArea;
while(lpVirtualArea)
{
if(((DWORD)lpStartAddr > (DWORD)lpVirtualArea->lpStartAddress) &&
((DWORD)lpStartAddr < (DWORD)lpVirtualArea->lpStartAddress
+ lpVirtualArea->dwAreaSize)) //Belong to this virtual area.
{
break;
}
lpVirtualArea = lpVirtualArea->lpNext;
}
if(NULL == lpVirtualArea) //Can not find a virtual area that countains
//the free block to be released.
{
//printf("\r\nFree a invalid block: can not find virtual area.");
return;
}
//
//Now,should insert the free block into heap object's free list.
//
lpFreeHeader->dwFlags |= BLOCK_FLAGS_FREE;
lpFreeHeader->dwFlags &= ~BLOCK_FLAGS_USED; //Clear the used flags.
lpFreeHeader->lpPrev = &lpHeapObj->FreeBlockHeader;
lpFreeHeader->lpNext = lpHeapObj->FreeBlockHeader.lpNext;
lpFreeHeader->lpPrev->lpNext = lpFreeHeader;
lpFreeHeader->lpNext->lpPrev = lpFreeHeader;
CombineBlock(lpVirtualArea,lpHeapObj); //Combine this virtual area.
//
//Now,should check if the whole virtual area is a free block.
//If so,delete the free block from free list,then release the
//virtual area to system.
//
lpFreeHeader = (__FREE_BLOCK_HEADER*)(lpVirtualArea->lpStartAddress);
if((lpFreeHeader->dwFlags & BLOCK_FLAGS_FREE) &&
(lpFreeHeader->dwBlockSize + sizeof(__FREE_BLOCK_HEADER)
== lpVirtualArea->dwAreaSize))
{
//
//Delete the free block from free list.
//
lpFreeHeader->lpPrev->lpNext = lpFreeHeader->lpNext;
lpFreeHeader->lpNext->lpPrev = lpFreeHeader->lpPrev;
//
//Now,should delete the virtual area node object from
//heap object's virtual list.
//
lpVirtualTmp = lpHeapObj->lpVirtualArea;
if(lpVirtualTmp == lpVirtualArea) //The first virtual node.
{
lpHeapObj->lpVirtualArea = lpVirtualArea->lpNext;
}
else //Not the first one.
{
while(lpVirtualTmp->lpNext != lpVirtualArea)
{
lpVirtualTmp = lpVirtualTmp->lpNext;
}
lpVirtualTmp->lpNext = lpVirtualArea->lpNext; //Delete it.
}
//
//Then,should release the virtual area and virtual area node
//object.
//
RELEASE_VIRTUAL_AREA((LPVOID)lpVirtualArea->lpStartAddress);
RELEASE_KERNEL_MEMORY((LPVOID)lpVirtualArea);
}
return;
}
/*************************************************************************
**************************************************************************
**************************************************************************
**************************************************************************
*************************************************************************/
//
//The declaration of HeapManager object.
//There is only one HeapManager object in whole system.
//
__HEAP_MANAGER HeapManager = {
CreateHeap, //CreateHeap routine.
DestroyHeap, //DestroyHeap routine.
DestroyAllHeap, //DestroyAllHeap routine.
HeapAlloc, //HeapAlloc routine.
HeapFree //HeapFree routine.
};
#endif
/*
//
//The following are malloc routine's implementation.
//This routine create a default heap,if not exists yet,then allocate
//memory from this default heap.
//
LPVOID malloc(DWORD dwSize)
{
#ifdef __CFG_SYS_VMM
DWORD dwFlags = 0;
LPVOID lpResult = NULL;
__HEAP_OBJECT* lpHeapObj = NULL;
DWORD dwHeapSize = 0;
if(0 == dwSize) //Invalid parameter.
return lpResult;
if(NULL == CURRENT_KERNEL_THREAD->lpDefaultHeap) //Should create one.
{
dwHeapSize = (dwSize + sizeof(__FREE_BLOCK_HEADER) > DEFAULT_VIRTUAL_AREA_SIZE) ?
(dwSize + sizeof(__FREE_BLOCK_HEADER)) : DEFAULT_VIRTUAL_AREA_SIZE;
lpHeapObj = CreateHeap(dwHeapSize);
if(NULL == lpHeapObj) //Can not create heap object.
return lpResult;
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
CURRENT_KERNEL_THREAD->lpDefaultHeap = (LPVOID)lpHeapObj;
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
}
else
{
lpHeapObj = (__HEAP_OBJECT*)CURRENT_KERNEL_THREAD->lpDefaultHeap;
}
return HeapAlloc(lpHeapObj,dwSize);
#else
return KMemAlloc(dwSize,KMEM_SIZE_TYPE_ANY);
#endif
}
//
//The implementation of free routine.
//This routine frees a memory block,to the default heap object of
//current kernel thread.
//
VOID free(LPVOID lpMemory)
{
#ifdef __CFG_SYS_VMM
__HEAP_OBJECT* lpHeapObj = NULL;
if(NULL == lpMemory)
return;
lpHeapObj = (__HEAP_OBJECT*)CURRENT_KERNEL_THREAD->lpDefaultHeap;
if(NULL == lpHeapObj) //Invalid case.
return;
HeapFree(lpMemory,lpHeapObj);
#else
KMemFree(lpMemory,KMEM_SIZE_TYPE_ANY,0);
#endif
}
*/
You can’t perform that action at this time.
