Release 940405
[wine/gsoc-2012-control.git] / memory / heap.c
blob71cb56113af002b590de9d12f916c2e81f413241
1 static char RCSId[] = "$Id: heap.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
2 static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "prototypes.h"
8 #include "segmem.h"
9 #include "heap.h"
10 #include "regfunc.h"
12 /* #define DEBUG_HEAP */
14 LHEAP *LocalHeaps = NULL;
16 /**********************************************************************
17 * HEAP_Init
19 void
20 HEAP_Init(MDESC **free_list, void *start, int length)
22 if (length < 2 * sizeof(MDESC))
23 return;
25 *free_list = (MDESC *) start;
26 (*free_list)->prev = NULL;
27 (*free_list)->next = NULL;
28 (*free_list)->length = length - sizeof(MDESC);
31 /**********************************************************************
32 * HEAP_Alloc
34 void *
35 HEAP_Alloc(MDESC **free_list, int flags, int bytes)
37 MDESC *m, *m_new;
39 #ifdef DEBUG_HEAP
40 printf("HeapAlloc: free_list %08x, flags %x, bytes %d\n",
41 free_list, flags, bytes);
42 #endif
45 * Find free block big enough.
47 for (m = *free_list; m != NULL; m = m->next)
49 if (m->length >= bytes && m->length < bytes + 4 * sizeof(MDESC))
51 break;
53 else if (m->length > bytes)
55 m_new = m + (bytes / sizeof(MDESC)) + 2;
56 if (m->prev == NULL)
57 *free_list = m_new;
58 else
59 m->prev->next = m_new;
61 if (m->next != NULL)
62 m->next->prev = m_new;
64 m_new->next = m->next;
65 m_new->prev = m->prev;
66 m_new->length = m->length - ((int) m_new - (int) m);
67 m->length -= (m_new->length + sizeof(MDESC));
69 m->prev = m;
70 m->next = m;
71 m->lock = 0;
72 m->flags = 0;
73 if (flags & GLOBAL_FLAGS_ZEROINIT)
74 memset(m + 1, 0, bytes);
75 #ifdef DEBUG_HEAP
76 printf("HeapAlloc: returning %08x\n", (m + 1));
77 #endif
78 return (void *) (m + 1);
82 if (m != NULL)
84 if (m->prev == NULL)
85 *free_list = m->next;
86 else
87 m->prev->next = m->next;
89 if (m->next != NULL)
90 m->next->prev = m->prev;
92 m->prev = m;
93 m->next = m;
94 m->lock = 0;
95 m->flags = 0;
96 if (flags & GLOBAL_FLAGS_ZEROINIT)
97 memset(m + 1, 0, bytes);
98 #ifdef DEBUG_HEAP
99 printf("HeapAlloc: returning %08x\n", (m + 1));
100 #endif
101 return (void *) (m + 1);
104 #ifdef DEBUG_HEAP
105 printf("HeapAlloc: returning %08x\n", 0);
106 #endif
107 return 0;
110 /**********************************************************************
111 * HEAP_ReAlloc
113 void *
114 HEAP_ReAlloc(MDESC **free_list, void *old_block,
115 int new_size, unsigned int flags)
117 MDESC *m_free;
118 MDESC *m;
121 * Check validity of block
123 m = (MDESC *) old_block - 1;
124 if (m->prev != m || m->next != m ||
125 ((int) m & 0xffff0000) != ((int) *free_list & 0xffff0000))
127 #ifdef DEBUG_HEAP
128 printf("Attempt to resize bad pointer, m = %08x, *free_list = %08x\n",
129 m, free_list);
130 #endif
131 return NULL;
135 * Check for grow block
137 if (new_size > m->length)
139 m_free = m + 1 + m->length / sizeof(MDESC);
140 if (m_free->next == m_free ||
141 m_free->prev == m_free ||
142 m_free->length + sizeof(MDESC) < new_size)
144 void *new_p = HEAP_Alloc(free_list, flags, new_size);
146 if (new_p ==NULL)
147 return NULL;
148 memcpy(new_p, old_block, m->length);
149 HEAP_Free(free_list, old_block);
150 return new_p;
153 if (m_free->prev == NULL)
154 *free_list = m_free->next;
155 else
156 m_free->prev->next = m_free->next;
158 if (m_free->next != NULL)
159 m_free->next->prev = m_free->prev;
161 m->length += sizeof(MDESC) + m_free->length;
162 if (flags & GLOBAL_FLAGS_ZEROINIT)
163 memset(m_free, '\0', sizeof(MDESC) + m_free->length);
167 * Check for shrink block.
169 if (new_size < m->length - 4 * sizeof(MDESC))
171 m_free = m + new_size / sizeof(MDESC) + 2;
172 m_free->next = m_free;
173 m_free->prev = m_free;
174 m_free->length = m->length - (int) m_free - (int) m;
175 m->length = (int) m_free - (int) (m + 1);
176 HEAP_Free(free_list, m_free + 1);
179 return old_block;
183 /**********************************************************************
184 * HEAP_Free
187 HEAP_Free(MDESC **free_list, void *block)
189 MDESC *m_free;
190 MDESC *m;
191 MDESC *m_prev;
194 * Validate pointer.
196 m_free = (MDESC *) block - 1;
197 if (m_free->prev != m_free || m_free->next != m_free ||
198 ((int) m_free & 0xffff0000) != ((int) *free_list & 0xffff0000))
200 #ifdef DEBUG_HEAP
201 printf("Attempt to free bad pointer,"
202 "m_free = %08x, *free_list = %08x\n",
203 m_free, free_list);
204 #endif
205 return -1;
209 * Find location in free list.
211 m_prev = NULL;
212 for (m = *free_list; m != NULL && m < m_free; m = m->next)
213 m_prev = m;
215 if (m_prev != NULL && (int) m_prev + m_prev->length > (int) m_free)
217 #ifdef DEBUG_HEAP
218 printf("Attempt to free bad pointer,"
219 "m_free = %08x, m_prev = %08x (length %x)\n",
220 m_free, m_prev, m_prev->length);
221 #endif
222 return -1;
225 if ((m != NULL && (int) m_free + m_free->length > (int) m) ||
226 (int) m_free + m_free->length > ((int) m_free | 0xffff))
228 #ifdef DEBUG_HEAP
229 printf("Attempt to free bad pointer,"
230 "m_free = %08x (length %x), m = %08x\n",
231 m_free, m_free->length, m);
232 #endif
233 return -1;
237 * Put block back in free list.
238 * Does it merge with the previos block?
240 if (m_prev != NULL)
242 if ((int) m_prev + m_prev->length == (int) m_free)
244 m_prev->length += sizeof(MDESC) + m_free->length;
245 m_free = m_prev;
247 else
249 m_prev->next = m_free;
250 m_free->prev = m_prev;
253 else
255 *free_list = m_free;
256 m_free->prev = NULL;
260 * Does it merge with the next block?
262 if (m != NULL)
264 if ((int) m_free + m_free->length == (int) m)
266 m_free->length += sizeof(MDESC) + m->length;
267 m_free->next = m->next;
269 else
271 m->prev = m_free;
272 m_free->next = m;
275 else
277 m_free->next = NULL;
280 return 0;
283 /**********************************************************************
284 * HEAP_LocalFindHeap
286 LHEAP *
287 HEAP_LocalFindHeap(unsigned short owner)
289 LHEAP *lh;
291 #ifdef DEBUG_HEAP
292 printf("HEAP_LocalFindHeap: owner %04x\n", owner);
293 #endif
295 for (lh = LocalHeaps; lh != NULL; lh = lh->next)
297 if (lh->selector == owner)
298 return lh;
301 return NULL;
304 /**********************************************************************
305 * HEAP_LocalInit
307 void
308 HEAP_LocalInit(unsigned short owner, void *start, int length)
310 LHEAP *lh;
312 #ifdef DEBUG_HEAP
313 printf("HEAP_LocalInit: owner %04x, start %08x, length %04x\n",
314 owner, start, length);
315 #endif
317 if (length < 2 * sizeof(MDESC))
318 return;
320 lh = (LHEAP *) malloc(sizeof(*lh));
321 if (lh == NULL)
322 return;
324 lh->next = LocalHeaps;
325 lh->selector = owner;
326 lh->local_table = NULL;
327 HEAP_Init(&lh->free_list, start, length);
328 LocalHeaps = lh;
331 /**********************************************************************
332 * WIN16_LocalAlloc
334 void *
335 WIN16_LocalAlloc(int flags, int bytes)
337 void *m;
339 #ifdef DEBUG_HEAP
340 printf("WIN16_LocalAlloc: flags %x, bytes %d\n", flags, bytes);
341 printf(" called from segment %04x\n", Stack16Frame[11]);
342 #endif
344 m = HEAP_Alloc(LOCALHEAP(), flags, bytes);
346 #ifdef DEBUG_HEAP
347 printf("WIN16_LocalAlloc: returning %x\n", (int) m);
348 #endif
349 return m;
352 /**********************************************************************
353 * WIN16_LocalCompact
356 WIN16_LocalCompact(int min_free)
358 MDESC *m;
359 int max_block;
361 max_block = 0;
362 for (m = *LOCALHEAP(); m != NULL; m = m->next)
363 if (m->length > max_block)
364 max_block = m->length;
366 return max_block;
369 /**********************************************************************
370 * WIN16_LocalFlags
372 unsigned int
373 WIN16_LocalFlags(unsigned int handle)
375 MDESC *m;
377 m = (MDESC *) (((int) *LOCALHEAP() & 0xffff0000) |
378 (handle & 0xffff)) - 1;
379 if (m->next != m || m->prev != m)
380 return 0;
382 return m->lock;
385 /**********************************************************************
386 * WIN16_LocalFree
388 unsigned int
389 WIN16_LocalFree(unsigned int handle)
391 unsigned int addr;
393 addr = ((int) *LOCALHEAP() & 0xffff0000) | (handle & 0xffff);
394 if (HEAP_Free(LOCALHEAP(), (void *) addr) < 0)
395 return handle;
396 else
397 return 0;
400 /**********************************************************************
401 * WIN16_LocalInit
403 unsigned int
404 WIN16_LocalInit(unsigned int segment, unsigned int start, unsigned int end)
406 unsigned short owner = HEAP_OWNER;
407 LHEAP *lh = HEAP_LocalFindHeap(owner);
409 if (segment == 0)
411 /* Get current DS */
412 segment = Stack16Frame[6];
415 if (lh == NULL)
417 HEAP_LocalInit(owner,
418 (void *) ((segment << 16) | start), end - start + 1);
420 else
422 HEAP_Init(&lh->free_list,
423 (void *) ((segment << 16) | start), end - start + 1);
426 return segment;
429 /**********************************************************************
430 * WIN16_LocalLock
432 void *
433 WIN16_LocalLock(unsigned int handle)
435 MDESC *m;
437 m = (MDESC *) (((int) *LOCALHEAP() & 0xffff0000) |
438 (handle & 0xffff)) - 1;
439 if (m->next != m || m->prev != m)
440 return 0;
442 m->lock++;
443 return (void *) (m + 1);
446 /**********************************************************************
447 * WIN16_LocalReAlloc
449 void *
450 WIN16_LocalReAlloc(unsigned int handle, int flags, int bytes)
452 void *m;
454 m = HEAP_ReAlloc(LOCALHEAP(), (void *)
455 (((int) *LOCALHEAP() & 0xffff0000) | (handle & 0xffff)),
456 bytes, flags);
458 return m;
461 /**********************************************************************
462 * WIN16_LocalSize
464 unsigned int
465 WIN16_LocalSize(unsigned int handle)
467 MDESC *m;
469 m = (MDESC *) (((int) *LOCALHEAP() & 0xffff0000) |
470 (handle & 0xffff)) - 1;
471 if (m->next != m || m->prev != m)
472 return 0;
474 return m->length;
477 /**********************************************************************
478 * WIN16_LocalUnlock
480 unsigned int
481 WIN16_LocalUnlock(unsigned int handle)
483 MDESC *m;
485 m = (MDESC *) (((int) *LOCALHEAP() & 0xffff0000) |
486 (handle & 0xffff)) - 1;
487 if (m->next != m || m->prev != m)
488 return 1;
490 if (m->lock > 0)
491 m->lock--;
493 return 0;
496 /**********************************************************************
497 * GetFreeSystemResources (user.284)
500 #define USERRESOURCES 2
501 #define GDIRESOURCES 1
502 #define SYSTEMRESOURCES 0
503 #include <user.h>
504 #include <gdi.h>
506 WORD GetFreeSystemResources(WORD SystemResourceType)
508 unsigned int GdiFree=0,GdiResult=0;
509 unsigned int UserFree=0,UserResult=0;
510 unsigned int result=0;
511 MDESC *m;
513 printf("GetFreeSystemResources(%u)\n",SystemResourceType);
515 switch(SystemResourceType) {
516 case(USERRESOURCES):
517 for (m = USER_Heap; m != NULL; m = m->next) /* add up free area in heap */
518 UserFree += m->length;
519 result=(UserFree*100)/65516; /* 65516 == 64K */
520 break;
521 case(GDIRESOURCES):
522 for (m = GDI_Heap; m != NULL; m = m->next)
523 GdiFree += m->length;
524 result=(GdiFree*100)/65516;
525 break;
526 case(SYSTEMRESOURCES):
527 for (m = USER_Heap; m != NULL; m = m->next)
528 UserFree += m->length;
529 UserResult=(UserFree*100)/65516;
530 for (m = GDI_Heap; m != NULL; m = m->next)
531 GdiFree += m->length;
532 GdiResult=(GdiFree*100)/65516;
533 result=(UserResult < GdiResult) ? UserResult:GdiResult;
534 break;
535 default:
536 result=0;
537 break;
539 return(result);