2 static char RCSId[] = "$Id: heap.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
3 static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
9 #include "prototypes.h"
15 /* #define DEBUG_HEAP */
19 LHEAP
*LocalHeaps
= NULL
;
22 HEAP_CheckHeap(MDESC
**free_list
)
26 for (m
= *free_list
; m
!= NULL
; m
= m
->next
)
28 if (((int) m
& 0xffff0000) != ((int) *free_list
& 0xffff0000))
29 { dprintf_heap(stddeb
,"Invalid block %p\n",m
);
32 if (m
->prev
&& (((int) m
->prev
& 0xffff0000) != ((int) *free_list
& 0xffff0000)))
33 { dprintf_heap(stddeb
,"Invalid prev %p from %p\n", m
->prev
, m
);
39 /**********************************************************************
43 HEAP_Init(MDESC
**free_list
, void *start
, int length
)
45 if (length
< 2 * sizeof(MDESC
))
48 *free_list
= (MDESC
*) start
;
49 (*free_list
)->prev
= NULL
;
50 (*free_list
)->next
= NULL
;
51 (*free_list
)->length
= length
- sizeof(MDESC
);
54 /**********************************************************************
58 HEAP_Alloc(MDESC
**free_list
, int flags
, int bytes
)
62 dprintf_heap(stddeb
,"HeapAlloc: free_list %08x(%08x), flags %x, bytes %d\n",
63 (unsigned int) free_list
, (unsigned int) *free_list
, flags
, bytes
);
64 if(debugging_heap
)HEAP_CheckHeap(free_list
);
67 * Find free block big enough.
69 for (m
= *free_list
; m
!= NULL
; m
= m
->next
)
71 if (m
->length
>= bytes
&& m
->length
< bytes
+ 4 * sizeof(MDESC
))
75 else if (m
->length
> bytes
)
77 m_new
= m
+ (bytes
/ sizeof(MDESC
)) + 2;
81 m
->prev
->next
= m_new
;
84 m
->next
->prev
= m_new
;
86 m_new
->next
= m
->next
;
87 m_new
->prev
= m
->prev
;
88 m_new
->length
= m
->length
- ((int) m_new
- (int) m
);
89 m
->length
-= (m_new
->length
+ sizeof(MDESC
));
95 if (flags
& GLOBAL_FLAGS_ZEROINIT
)
96 memset(m
+ 1, 0, bytes
);
97 dprintf_heap(stddeb
,"HeapAlloc: returning %08x\n",
98 (unsigned int) (m
+ 1));
99 if(debugging_heap
)HEAP_CheckHeap(free_list
);
100 return (void *) (m
+ 1);
107 *free_list
= m
->next
;
109 m
->prev
->next
= m
->next
;
112 m
->next
->prev
= m
->prev
;
118 if (flags
& GLOBAL_FLAGS_ZEROINIT
)
119 memset(m
+ 1, 0, bytes
);
120 dprintf_heap(stddeb
,"HeapAlloc: returning %08x\n",
121 (unsigned int) (m
+ 1));
122 if(debugging_heap
)HEAP_CheckHeap(free_list
);
123 return (void *) (m
+ 1);
126 dprintf_heap(stddeb
,"HeapAlloc: returning %08x\n", 0);
127 if(debugging_heap
)HEAP_CheckHeap(free_list
);
131 /**********************************************************************
135 HEAP_ReAlloc(MDESC
**free_list
, void *old_block
,
136 int new_size
, unsigned int flags
)
143 return HEAP_Alloc(free_list
, flags
, new_size
);
146 * Check validity of block
148 m
= (MDESC
*) old_block
- 1;
150 dprintf_heap(stddeb
,"HEAP_ReAlloc new_size=%d !\n",
151 (unsigned int) new_size
);
152 dprintf_heap(stddeb
,"HEAP_ReAlloc old_block=%08X !\n",
153 (unsigned int) old_block
);
154 dprintf_heap(stddeb
,"HEAP_ReAlloc m=%08X free_list=%08X !\n",
155 (unsigned int) m
, (unsigned int) free_list
);
156 dprintf_heap(stddeb
,"HEAP_ReAlloc m->prev=%08X !\n",
157 (unsigned int) m
->prev
);
158 dprintf_heap(stddeb
,"HEAP_ReAlloc m->next=%08X !\n",
159 (unsigned int) m
->next
);
160 dprintf_heap(stddeb
,"HEAP_ReAlloc *free_list=%08X !\n",
161 (unsigned int) *free_list
);
162 if(debugging_heap
)HEAP_CheckHeap(free_list
);
164 if (m
->prev
!= m
|| m
->next
!= m
||
165 ((int) m
& 0xffff0000) != ((int) *free_list
& 0xffff0000))
167 fprintf(stderr
,"Attempt to resize bad pointer, m = %p, *free_list = %p\n",
169 HEAP_CheckHeap(free_list
);
174 * Check for grow block
177 dprintf_heap(stddeb
,"HEAP_ReAlloc Check for grow block !\n");
178 if (new_size
> m
->length
)
180 m_free
= m
+ 1 + m
->length
/ sizeof(MDESC
);
181 if (m_free
->next
== m_free
||
182 m_free
->prev
== m_free
||
183 m_free
->length
+ 2*sizeof(MDESC
) < new_size
- m
->length
)
185 void *new_p
= HEAP_Alloc(free_list
, flags
, new_size
);
188 memcpy(new_p
, old_block
, m
->length
);
189 HEAP_Free(free_list
, old_block
);
190 if(debugging_heap
)HEAP_CheckHeap(free_list
);
194 if (m_free
->prev
== NULL
)
195 *free_list
= m_free
->next
;
197 m_free
->prev
->next
= m_free
->next
;
199 if (m_free
->next
!= NULL
)
200 m_free
->next
->prev
= m_free
->prev
;
202 m
->length
+= sizeof(MDESC
) + m_free
->length
;
204 dprintf_heap(stddeb
,"HEAP_ReAlloc before GLOBAL_FLAGS_ZEROINIT !\n");
205 if (flags
& GLOBAL_FLAGS_ZEROINIT
)
206 memset(m_free
, '\0', sizeof(MDESC
) + m_free
->length
);
210 * Check for shrink block.
212 dprintf_heap(stddeb
,"HEAP_ReAlloc Check for shrink block !\n");
213 if (new_size
+ 4*sizeof(MDESC
) < m
->length
)
215 m_free
= m
+ new_size
/ sizeof(MDESC
) + 2;
216 m_free
->next
= m_free
;
217 m_free
->prev
= m_free
;
218 m_free
->length
= m
->length
- ((int) m_free
- (int) m
);
219 m
->length
= (int) m_free
- (int) (m
+ 1);
220 HEAP_Free(free_list
, m_free
+ 1);
223 if(debugging_heap
)HEAP_CheckHeap(free_list
);
228 /**********************************************************************
232 HEAP_Free(MDESC
**free_list
, void *block
)
238 dprintf_heap(stddeb
,"HeapFree: free_list %p, block %p\n",
240 if(debugging_heap
)HEAP_CheckHeap(free_list
);
245 m_free
= (MDESC
*) block
- 1;
246 if (m_free
->prev
!= m_free
|| m_free
->next
!= m_free
)
248 fprintf(stderr
,"Attempt to free bad pointer,"
249 "m_free = %p, *free_list = %p\n",
254 if (*free_list
== NULL
)
257 (*free_list
)->next
= NULL
;
258 (*free_list
)->prev
= NULL
;
261 else if (((int) m_free
& 0xffff0000) != ((int) *free_list
& 0xffff0000))
263 fprintf(stderr
,"Attempt to free bad pointer,"
264 "m_free = %p, *free_list = %p\n",
270 * Find location in free list.
273 for (m
= *free_list
; m
!= NULL
&& m
< m_free
; m
= m
->next
)
276 if (m_prev
!= NULL
&& (int) m_prev
+ m_prev
->length
> (int) m_free
)
278 fprintf(stderr
,"Attempt to free bad pointer,"
279 "m_free = %p, m_prev = %p (length %x)\n",
280 m_free
, m_prev
, m_prev
->length
);
284 if ((m
!= NULL
&& (int) m_free
+ m_free
->length
> (int) m
) ||
285 (int) m_free
+ m_free
->length
> ((int) m_free
| 0xffff))
287 fprintf(stderr
,"Attempt to free bad pointer,"
288 "m_free = %p (length %x), m = %p\n",
289 m_free
, m_free
->length
, m
);
294 * Put block back in free list.
295 * Does it merge with the previos block?
299 if ((int) m_prev
+ m_prev
->length
== (int) m_free
)
301 m_prev
->length
+= sizeof(MDESC
) + m_free
->length
;
306 m_prev
->next
= m_free
;
307 m_free
->prev
= m_prev
;
317 * Does it merge with the next block?
321 if ((int) m_free
+ m_free
->length
== (int) m
)
323 m_free
->length
+= sizeof(MDESC
) + m
->length
;
324 m_free
->next
= m
->next
;
337 if(debugging_heap
)HEAP_CheckHeap(free_list
);
341 /**********************************************************************
342 * HEAP_CheckLocalHeaps
345 HEAP_CheckLocalHeaps(char *file
,int line
)
348 dprintf_heap(stddeb
,"CheckLocalHeaps called from %s %d\n",file
,line
);
349 for(lh
=LocalHeaps
; lh
!=NULL
; lh
= lh
->next
)
350 { dprintf_heap(stddeb
,"Checking heap %p, free_list %p\n",
352 HEAP_CheckHeap(&lh
->free_list
);
357 /**********************************************************************
361 HEAP_LocalFindHeap(unsigned short owner
)
365 dprintf_heap(stddeb
,"HEAP_LocalFindHeap: owner %04x\n", owner
);
367 for (lh
= LocalHeaps
; lh
!= NULL
; lh
= lh
->next
)
369 if (lh
->selector
== owner
)
373 dprintf_heap(stddeb
,"Warning: Local heap not found\n");
377 /**********************************************************************
381 HEAP_LocalInit(unsigned short owner
, void *start
, int length
)
385 dprintf_heap(stddeb
,"HEAP_LocalInit: owner %04x, start %p, length %04x\n"
386 ,owner
, start
, length
);
388 if (length
< 2 * sizeof(MDESC
))
391 lh
= (LHEAP
*) malloc(sizeof(*lh
));
395 lh
->next
= LocalHeaps
;
396 lh
->selector
= owner
;
397 lh
->local_table
= NULL
;
399 HEAP_Init(&lh
->free_list
, start
, length
);
400 dprintf_heap(stddeb
,"HEAP_LocalInit: free_list %p, length %04x, prev %p, next %p\n",&lh
->free_list
,lh
->free_list
->length
, lh
->free_list
->prev
,lh
->free_list
->next
);
404 /**********************************************************************
408 HEAP_LocalSize(MDESC
**free_list
, unsigned int handle
)
412 m
= (MDESC
*) (((int) *free_list
& 0xffff0000) |
413 (handle
& 0xffff)) - 1;
414 if (m
->next
!= m
|| m
->prev
!= m
)
420 /**********************************************************************
424 WIN16_LocalAlloc(int flags
, int bytes
)
428 dprintf_heap(stddeb
,"WIN16_LocalAlloc: flags %x, bytes %d\n", flags
,bytes
);
429 dprintf_heap(stddeb
," called from segment %04x, ds=%04x\n", Stack16Frame
[11],Stack16Frame
[6]);
431 m
= HEAP_Alloc(LOCALHEAP(), flags
, bytes
);
433 dprintf_heap(stddeb
,"WIN16_LocalAlloc: returning %x\n", (int) m
);
437 /**********************************************************************
441 WIN16_LocalCompact(int min_free
)
447 for (m
= *LOCALHEAP(); m
!= NULL
; m
= m
->next
)
448 if (m
->length
> max_block
)
449 max_block
= m
->length
;
454 /**********************************************************************
458 WIN16_LocalFlags(unsigned int handle
)
462 m
= (MDESC
*) (((int) *LOCALHEAP() & 0xffff0000) |
463 (handle
& 0xffff)) - 1;
464 if (m
->next
!= m
|| m
->prev
!= m
)
470 /**********************************************************************
474 WIN16_LocalFree(unsigned int handle
)
478 addr
= ((int) *LOCALHEAP() & 0xffff0000) | (handle
& 0xffff);
479 if (HEAP_Free(LOCALHEAP(), (void *) addr
) < 0)
485 /**********************************************************************
489 WIN16_LocalInit(unsigned int segment
, unsigned int start
, unsigned int end
)
491 unsigned short owner
= HEAP_OWNER
;
492 LHEAP
*lh
= HEAP_LocalFindHeap(owner
);
497 segment
= Stack16Frame
[6];
500 dprintf_heap(stddeb
, "WIN16_LocalInit segment=%04x start=%04x end=%04x\n", segment
, start
, end
);
502 /* start=0 doesn't mean the first byte of the segment if the segment
503 is an auto data segment. Instead it should start after the actual
504 data (and the stack if there is one). As we don't know the length
505 of the data and stack right now, we simply put the local heap at the
506 end of the segment */
507 if ((start
==0)&&(Segments
[segment
>>3].owner
==segment
))
510 start
= Segments
[segment
>>3].length
-end
-2;
511 end
= Segments
[segment
>>3].length
-1;
512 dprintf_heap(stddeb
, "Changed to start=%04x end=%04x\n",start
,end
);
517 HEAP_LocalInit(owner
,
518 (void *) ((segment
<< 16) | start
), end
- start
+ 1);
522 HEAP_Init(&lh
->free_list
,
523 (void *) ((segment
<< 16) | start
), end
- start
+ 1);
525 dprintf_heap(stddeb
,"WIN16_LocalInit // return segment=%04X !\n", segment
);
529 /**********************************************************************
533 WIN16_LocalLock(unsigned int handle
)
537 m
= (MDESC
*) (((int) *LOCALHEAP() & 0xffff0000) |
538 (handle
& 0xffff)) - 1;
539 if (m
->next
!= m
|| m
->prev
!= m
)
543 return (void *) (m
+ 1);
546 /**********************************************************************
550 WIN16_LocalReAlloc(unsigned int handle
, int bytes
, int flags
)
553 dprintf_heap(stddeb
,"WIN16_LocalReAlloc(%04X, %d, %04X); !\n",
554 handle
, bytes
, flags
);
555 dprintf_heap(stddeb
,"WIN16_LocalReAlloc // LOCALHEAP()=%p !\n",
557 dprintf_heap(stddeb
,"WIN16_LocalReAlloc // *LOCALHEAP()=%p !\n",
559 m
= HEAP_ReAlloc(LOCALHEAP(), (void *)
560 (((int) *LOCALHEAP() & 0xffff0000) | (handle
& 0xffff)),
566 /**********************************************************************
570 WIN16_LocalSize(unsigned int handle
)
574 m
= (MDESC
*) (((int) *LOCALHEAP() & 0xffff0000) |
575 (handle
& 0xffff)) - 1;
576 if (m
->next
!= m
|| m
->prev
!= m
)
582 /**********************************************************************
586 WIN16_LocalUnlock(unsigned int handle
)
590 m
= (MDESC
*) (((int) *LOCALHEAP() & 0xffff0000) |
591 (handle
& 0xffff)) - 1;
592 if (m
->next
!= m
|| m
->prev
!= m
)
601 /**********************************************************************
602 * WIN16_LocalHandleDelta
605 WIN16_LocalHandleDelta(unsigned int new_delta
)
609 lh
= HEAP_LocalFindHeap(HEAP_OWNER
);
614 lh
->delta
= new_delta
;
619 /**********************************************************************
620 * GetFreeSystemResources (user.284)
623 #define USERRESOURCES 2
624 #define GDIRESOURCES 1
625 #define SYSTEMRESOURCES 0
629 WORD
GetFreeSystemResources(WORD SystemResourceType
)
631 unsigned int GdiFree
=0,GdiResult
=0;
632 unsigned int UserFree
=0,UserResult
=0;
633 unsigned int result
=0;
635 dprintf_heap(stddeb
,"GetFreeSystemResources(%u)\n",SystemResourceType
);
636 switch(SystemResourceType
) {
638 for (m
= USER_Heap
; m
!= NULL
; m
= m
->next
) /* add up free area in heap */
639 UserFree
+= m
->length
;
640 result
=(UserFree
*100)/65516; /* 65516 == 64K */
643 for (m
= GDI_Heap
; m
!= NULL
; m
= m
->next
)
644 GdiFree
+= m
->length
;
645 result
=(GdiFree
*100)/65516;
647 case(SYSTEMRESOURCES
):
648 for (m
= USER_Heap
; m
!= NULL
; m
= m
->next
)
649 UserFree
+= m
->length
;
650 UserResult
=(UserFree
*100)/65516;
651 for (m
= GDI_Heap
; m
!= NULL
; m
= m
->next
)
652 GdiFree
+= m
->length
;
653 GdiResult
=(GdiFree
*100)/65516;
654 result
=(UserResult
< GdiResult
) ? UserResult
:GdiResult
;