diff options
Diffstat (limited to 'pico/msmem.c')
-rw-r--r-- | pico/msmem.c | 1301 |
1 files changed, 0 insertions, 1301 deletions
diff --git a/pico/msmem.c b/pico/msmem.c deleted file mode 100644 index 4565e5dc..00000000 --- a/pico/msmem.c +++ /dev/null @@ -1,1301 +0,0 @@ -#ifndef MSC_MALLOC - -#define WIN31 -#define STRICT - -#include <windows.h> -#include <toolhelp.h> -#include <stdio.h> - -#include "mswin.h" - - - - - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * - * Memory allocation routines. - * - *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ - -/* - * The plan is to allocate small blocks in the local heap and - * large blocks in the global heap. The intention is to keep - * the number of global allocations to a minimum. - * - * The boundry between small memory and large memory is - * controld by the constant SMALL_MEM_BOUNDRY. Blocks smaller - * than SMALL_MEM_BOUNDRY go into the local heap. This should - * be set large enough to capture the majority of small memory - * blocks in the local heap. But if it is too large, the local - * heap will fill up and we will end up allocating a lot of small - * blocks in the global heap. - * - * Unfortunatly, pine seems to need a large stack. With the - * stack, some global data, and the heap all cramed in to a 64K - * segment we end up with a heap that is smaller than ideal. - * This could be improved by reducing the size of the stack, or - * by moving the heap to a seperate memory block. I did a little - * work on moving the heap, but was not successful. My attepts - * can be seen in the function MemATest(). - * - * Currently (7/8/94) I've set the stack to 32K (in pine/makefile.win), - * the heap to 12K, and the small memory boundry to 32 bytes. - * Statistics on pine memory allocation suggest that it would be better - * to have a 25K local heap and a 95 byte small memory boundry. - * - * Statistics on memory use can be gathered by logging memory debugging - * to a file, then running the following awk script: - * - - # mem.awk - # - # Looks through log and find blocks that were allocated but not - # freed uses block id numbers, rather than addresses, since this is - # more accurate (and since this is what block ids exist!) - # - # awk may run out of memory if the logfile gets too big. If this - # happens, then another strategy will be needed... - # - - BEGIN { - FS = "[ ()]+"; - - b[0] = 16; - b[1] = 32; - b[2] = 64; - b[3] = 96; - b[4] = 128; - b[5] = 256; - b[6] = 512; - b[7] = 1024; - b[8] = 2048; - b[9] = 4096; - b[10] = 9600; - b[11] = 20000; - b[12] = 40000; - b[13] = 80000; - b[14] = 200000000; - b[15] = 0; - bcount = 15; - for (i = 0; i < bcount; ++i) - c[i] = 0; - - maxmem = 0; - maxsmallmem = 0; - - allocs = 0; - frees = 0; - globalallocs = 0; - pallocs = 0; - pfrees = 0; - } - - { - #print "one", $1, "two", $2, "three", $3, "four ", $4, "five ", $5; - if( $1 == "MemAlloc:" ) { - m[$5] = $0; - - ++allocs; - if ($9 == 1) ++globalallocs; - - for (i = 0; i < bcount; ++i) { - if (b[i] > $7) { - ++c[i]; - break; - } - } - } - else if( $1 == "MemFree:" ) { - delete m[$5]; - ++frees; - } - if( $1 == "PageAlloc:" ) { - p[$5] = $0; - - ++pallocs; - } - else if( $1 == "PageFree:" ) { - delete p[$5]; - ++pfrees; - } - else if ($1 == "Memory") { - if ($6 > maxmem) maxmem = $6; - } - else if ($1 == "Small") { - if ($7 > maxsmallmem) maxsmallmem = $7; - } - } - - - END { - for( i in m ) { - print m[i] - } - for (i in p) { - print p[i] - } - - cumulative = 0; - for (i = 0; i < bcount; ++i) { - cumulative += c[i]; - printf "%9d : %5d (%5d)\n", b[i], c[i], cumulative; - } - - print; - print "Max memory use: ", maxmem; - print "Max small memory use: ", maxsmallmem; - print; - print "Local allocations ", allocs - globalallocs; - print "Global allocations ", globalallocs; - print "Total allocations ", allocs; - print "Total memory frees ", frees; - print "Blocks not freed ", allocs - frees; - print; - print "Page allocations ", pallocs; - print "Page frees ", pfrees; - print "Pages not freed ", pallocs - pfrees; - } - - * - * Each memory block is assigned a unique id. This is only used - * to match allocations with frees in the debug log. - */ - - - -/* - * SEGHEAP selectes between two different implementations of the memory - * management functions. Defined and it uses a sub allocation scheme. - * Undefined and it comples a direct allocation scheme. - * - * The sub allocation scheme is greatly prefered because it greatly reduces - * the number of global memory allocations. - */ -#define SEGHEAP /* Use the sub allocation scheme. */ - - - - -#define MEM_DEBUG /* Compile in memory debugging code.*/ -#define MEM_DEBUG_LEVEL 8 /* Pine debug level at which memory - * debug messages will be generated.*/ -#ifdef MEM_DEBUG -static int MemDebugLevel = 0; /* Doing debugging. */ -static FILE *MemDebugFile = NULL; /* File to write to. */ -#endif - - - -#ifdef DEBUG -#define LOCAL -#else -#define LOCAL static -#endif - - -#define GET_SEGMENT(x) (0xffff & ((DWORD)(x) >> 16)) -#define GET_OFFSET(x) (0xffff & (DWORD)(x)) - - -#undef malloc -#undef realloc -#undef free - - -void MemATest (void); - - - - - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * - * Standard memory allcation functions. - * - *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ - - -void * -malloc (size_t size) -{ - return (MemAlloc (size)); -} - - -void __far * -_fmalloc (size_t size) -{ - return (MemAlloc (size)); -} - - -void __far * -realloc (void *memblock, size_t size) -{ - return (MemRealloc (memblock, size)); -} - - -void __far * -_frealloc (void *memblock, size_t size) -{ - return (MemRealloc (memblock, size)); -} - - -void -free (void *memblock) -{ - MemFree (memblock); -} - -void -_ffree (void *memblock) -{ - MemFree (memblock); -} - - -/* - * Turn on memory debugging and specify file to write to. - */ -void -MemDebug (int debug, FILE *debugFile) -{ -#ifdef MEM_DEBUG - if (debugFile == NULL) { - MemDebugLevel = 0; - MemDebugFile = NULL; - } - else { - MemDebugLevel = debug; - MemDebugFile = debugFile; - fprintf (MemDebugFile, "Memory Debuging set on\n"); - } -#endif /* MEM_DEBUG */ -} - - - - - - - -#ifdef SEGHEAP - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * - * SEGHEAP Memory allocation routines. - * - *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ - -/* - * This implementation allocates memory in pages then sub alloates from the - * pages. This greatly reduces the number of global memory blocks allocated. - * This code originally written by Stephen Chung and posted to a Usenet news - * group. I've modified them for use in Pine. The author says: - * - * - * Copyright (C) Stephen Chung, 1991-1992. All rights reserved. - * - * Afterwords - * ---------- - * - * Theoretically, you are required to obtain special approval from me (because - * I copyrighted these routines) if you want to use them in your programs. - * However, I usually don't really care if you are not using these routines in - * a commercial, shareware etc. product. - * - * Any questions and/or bug fixes, please send email to: - * - * Stephen Chung stephenc@cunixf.cc.columbia.edu - * - * If it bounces, then try schung@cogsci.Berkeley.EDU - * - * Have fun! - * - */ - - -/* - * The folloing control debugging code for testing out of memory conditions. - * there are to test code. - * - * MEM_ALLOC_LIMT - * Setting this to anything other than zero will limit memory allocation - * to (rougly) that many bytes. - * - * MEM_FAIL_SOON - * Compiles in a function which will cause the memory allocation to fail - * soon after that function is called. this can be used to test - * mem alloc failurs in specific code segments. - */ -#define MEM_ALLOC_LIMIT 0 -#define MEM_FAIL_SOON 0 - - -#if MEM_FAIL_SOON -static long MemFailSoonLimit = 0; -#endif - - - -#define MAGIC 0x42022667 -#define MAGIC2 0x56743296 - -typedef struct MemoryStruct { - long int magic; - void far *page; - WORD id; - MemSize size; - BOOL allocated; - struct MemoryStruct far *next, far *prev; - long int magic2; -} MEMHEADER; - -typedef struct PageHeaderStruct { - long int magic; - HANDLE handle; - WORD id; - MemSize size; - MemSize used; - MemSize overhead; - MEMHEADER far *data, far *empty; - struct PageHeaderStruct far *next, far *prev; - long int magic2; -} MEMPAGEHEADER; - -typedef struct { - MEMPAGEHEADER far *pages; - int nr_pages; -} MAINMEMHEADER; - -#define PAGESIZE (6 * 1024) -#define USEABLESIZE (PAGESIZE - sizeof(MEMPAGEHEADER) - sizeof(MEMHEADER)) - - -LOCAL MAINMEMHEADER MemHeader = { NULL, 0 }; -LOCAL WORD MemID = 0; /* Keep track of ID. */ -LOCAL WORD PageID = 0; -LOCAL unsigned long MemInUse = 0; /* Total bytes in use. */ -LOCAL unsigned long MemInUseMax = 0; /* max in use at one time. */ -LOCAL unsigned long PageMemInUse = 0; -LOCAL unsigned long PageMemInUseMax = 0; - - - -static MEMPAGEHEADER far * -AddPage(MemSize n) -{ - void far *cp; - MEMHEADER far *mp; - MEMPAGEHEADER far *p; - HANDLE handle = NULL; - - -#if MEM_ALLOC_LIMIT - if (n + PageMemInUse > MEM_ALLOC_LIMIT) { - MessageBox (NULL, "PageAlloc: Above preset limit, allocation fails", - "Out Of Memory", MB_ICONSTOP | MB_OK); - return (NULL); - } -#endif - - handle = GlobalAlloc(GHND, n); - if (handle == NULL) { -#ifdef MEM_DEBUG - if (MemDebugLevel >= 1) - fprintf (MemDebugFile, "***\n*** Out of memory: allocating %d bytes\n***\n", n); -#endif - return (NULL); - } - - if (MemHeader.pages == NULL || MemHeader.nr_pages <= 0) { - p = MemHeader.pages = (MEMPAGEHEADER far *) GlobalLock(handle); - p->prev = NULL; - } else { - for (p = MemHeader.pages; p->next != NULL; p = p->next); - p->next = (MEMPAGEHEADER far *) GlobalLock(handle); - p->next->prev = p; - p = p->next; - } - - p->magic = MAGIC; - p->handle = handle; - p->next = NULL; - p->id = PageID++; - p->size = n; - p->used = 0; - p->overhead = sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER); - p->magic2 = MAGIC2; - - cp = ((char far *) p) + sizeof(MEMPAGEHEADER); - mp = (MEMHEADER far *) cp; - - p->data = p->empty = mp; - - mp->magic = 0L; - mp->magic2 = 0L; - mp->allocated = FALSE; - mp->page = p; - mp->size = p->size - p->overhead; - mp->next = mp->prev = NULL; - - MemHeader.nr_pages++; - - -#ifdef MEM_DEBUG - if (MemDebugLevel >= MEM_DEBUG_LEVEL) { - fprintf (MemDebugFile, "PageAlloc: addr(%lx) id(%u) size(%ld) global(%d)\n", - p, p->id, (long)n, 1); - fflush (MemDebugFile); - } -#endif /* MEM_DEBUG */ - - PageMemInUse += n; - if (PageMemInUse > PageMemInUseMax) - PageMemInUseMax = PageMemInUse; - - - return (p); -} - - - -static void -DeletePage (MEMPAGEHEADER far *p) -{ -#ifdef MEM_DEBUG - /* Deubgging info... */ - if (MemDebugLevel >= 4) { - if (PageMemInUse == PageMemInUseMax) - fprintf (MemDebugFile, "Page usage is up to %lu\n", PageMemInUseMax); - } - if (MemDebugLevel >= MEM_DEBUG_LEVEL) { - fprintf (MemDebugFile, "PageFree: addr(%lx) id(%u)\n", - p, p->id); - fflush (MemDebugFile); - } -#endif /* MEM_DEBUG */ - - PageMemInUse -= p->size; - - - if (p->next == NULL && p->prev == NULL) { - MemHeader.pages = NULL; - MemHeader.nr_pages = 0; - GlobalUnlock (p->handle); - GlobalFree (p->handle); - } else { - if (p == MemHeader.pages) MemHeader.pages = p->next; - MemHeader.nr_pages--; - - if (p->prev != NULL) p->prev->next = p->next; - if (p->next != NULL) p->next->prev = p->prev; - - GlobalUnlock (p->handle); - GlobalFree (p->handle); - } -} - - -/* - * Segmented heap memory allocation. - */ - -MemPtr -_MemAlloc (MemSize n, char __far * file, int line) -{ - MEMPAGEHEADER far *p; - MEMHEADER far *mp; - char far *cp; - - if (n >= 65535) { - assert (n < 65535); - goto AllocFail; - } - -#if MEM_FAIL_SOON - if (MemFailSoonLimit != 0 && MemFailSoonLimit < MemInUse + n) { - MessageBox (NULL, "MemAlloc: Told to fail here, allocation fails", - "Out Of Memory", MB_ICONSTOP | MB_OK); - return (NULL); - } -#endif - - /* Larger than page size? */ - - if (n > USEABLESIZE) { - p = AddPage(n + sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER)); - if (p == NULL) - goto AllocFail; - - mp = p->data; - mp->magic = MAGIC; - mp->magic2 = MAGIC2; - mp->id = MemID++; - mp->allocated = TRUE; - - - p->used = n; - p->empty = NULL; - - cp = ((char far *) mp) + sizeof(MEMHEADER); -#ifdef MEM_DEBUG - if (MemDebugLevel >= MEM_DEBUG_LEVEL) { - fprintf (MemDebugFile, "MemAlloc: addr(%lx) id(%u) size(%ld) global(%d)\n", - cp, mp->id, (long)n, 0); - fflush (MemDebugFile); - } -#endif /* MEM_DEBUG */ - - MemInUse += n; - if (MemInUse > MemInUseMax) - MemInUseMax = MemInUse; - return ((MemPtr) cp); - } - - - /* Search for the hole */ - - for (p = MemHeader.pages; p != NULL; p = p->next) { - /* Scan the chains */ - if (p->size - p->used - p->overhead <= 0) continue; - if (p->empty == NULL) continue; - - for (mp = p->empty; mp != NULL; mp = mp->next) { - if (!mp->allocated && mp->size >= n) break; - } - - if (mp != NULL) break; - } - - /* New page needed? */ - - if (p == NULL) { - p = AddPage(PAGESIZE); - if (p == NULL) - goto AllocFail; - mp = p->data; - } - - /* Do we need to break it up? */ - - if (mp->size - n > sizeof(MEMHEADER)) { - MEMHEADER far *mp2; - - cp = ((char far *) mp) + n + sizeof(MEMHEADER); - mp2 = (MEMHEADER far *) cp; - - mp2->magic = 0L; - mp2->magic2 = 0L; - mp2->allocated = FALSE; - mp2->page = p; - mp2->size = mp->size - n - sizeof(MEMHEADER); - - mp2->next = mp->next; - mp2->prev = mp; - if (mp->next != NULL) mp->next->prev = mp2; - mp->next = mp2; - - - p->overhead += sizeof(MEMHEADER); - - mp->size = n; - } - - mp->magic = MAGIC; - mp->magic2 = MAGIC2; - mp->allocated = TRUE; - mp->id = MemID++; - - p->used += n; - cp = ((char far *) mp) + sizeof(MEMHEADER); - - - /* Debugging info... */ -#ifdef MEM_DEBUG - if (MemDebugLevel >= MEM_DEBUG_LEVEL) { - fprintf (MemDebugFile, "MemAlloc: addr(%lx) id(%u) size(%ld) global(%d)\n", - cp, mp->id, (long)n, 0); - fflush (MemDebugFile); - } -#endif /* MEM_DEBUG */ - - MemInUse += n; - if (MemInUse > MemInUseMax) - MemInUseMax = MemInUse; - - - /* Search for the next empty hole */ - - for (; mp != NULL; mp = mp->next) { - if (!mp->allocated && mp->size > 0) break; - } - - p->empty = mp; - - return ((MemPtr) cp); - - -AllocFail: -#if 0 - assert (FALSE /* Memory allocation failed! */);*/ -#endif - return (NULL); -} - - - -/* - * Segmented heap memory free. - */ -int -_MemFree (MemPtr vp, char __far *file, int line) -{ - MEMPAGEHEADER far *p; - MEMHEADER far *mp, far *mp2; - char far *cp; - - if (vp == NULL) - return (0); - - - cp = ((char far *) vp) - sizeof(MEMHEADER); - mp = (MEMHEADER far *) cp; - - if (mp->magic != MAGIC || mp->magic2 != MAGIC2|| !mp->allocated) { - assert (mp->magic == MAGIC); - assert (mp->magic2 == MAGIC2); - assert (mp->allocated); - return (-1); - } - -#ifdef MEM_DEBUG - /* Deubgging info... */ - if (MemDebugLevel >= 4) { - if (MemInUse == MemInUseMax) - fprintf (MemDebugFile, "Memory usage is up to %lu\n", MemInUseMax); - } - if (MemDebugLevel >= MEM_DEBUG_LEVEL) { - fprintf (MemDebugFile, "MemFree: addr(%lx) id(%u)\n", vp, mp->id); - fflush (MemDebugFile); - } -#endif /* MEM_DEBUG */ - - MemInUse -= mp->size; - - - p = (MEMPAGEHEADER far *) mp->page; - p->used -= mp->size; - - mp->magic = 0L; - mp->magic2 = 0L; - mp->allocated = FALSE; - - /* Merge? */ - - mp2 = mp->prev; - - if (mp2 != NULL && !mp2->allocated) { - mp2->next = mp->next; - if (mp->next != NULL) mp->next->prev = mp2; - mp2->size += mp->size + sizeof(MEMHEADER); - - p->overhead -= sizeof(MEMHEADER); - - mp = mp2; - } - - mp2 = mp->next; - - if (mp2 != NULL && !mp2->allocated) { - mp->next = mp2->next; - if (mp2->next != NULL) - mp2->next->prev = mp; - - mp->size += mp2->size + sizeof(MEMHEADER); - - p->overhead -= sizeof(MEMHEADER); - } - - if (mp->prev == NULL && mp->next == NULL) { - DeletePage(p); - } else { - if (p->empty == NULL || mp < p->empty) p->empty = mp; - } - return (0); -} - - - -MemPtr -_MemRealloc (MemPtr p, MemSize n, char __far *file, int line) -{ - MEMHEADER far *mp; - char far *cp; - - if (p != NULL) { - /* Block already large enough? */ - cp = ((char far *) p) - sizeof(MEMHEADER); - mp = (MEMHEADER far *) cp; - - if (mp->magic != MAGIC || mp->magic2 != MAGIC2) { - assert (mp->magic == MAGIC); - assert (mp->magic2 == MAGIC2); - return (p); - } - - if (mp->size >= n) return (p); /* No need to do anything */ - } - /* Else swap to another block */ - - cp = MemAlloc (n); - if (cp == NULL) - return (NULL); - - if (p != NULL) { - _fmemcpy(cp, p, (size_t)((mp->size >= n) ? n : mp->size)); - MemFree (p); - } - - return ((void far *) cp); -} - - - -void -MemFailSoon (MemSize n) -{ -#if MEM_FAIL_SOON - MemFailSoonLimit = MemInUse + n; -#ifdef MEM_DEBUG - if (MemDebugLevel >= 1) { - fprintf (MemDebugFile, - "MemFailSoon: Fail when allocation increases by %ld (Max %ld)\n", - n, MemFailSoonLimit); - } -#endif -#endif -} - - - - - -MemSize -MemBlkSize (MemPtr p) -{ - MEMHEADER far *mp; - char far *cp; - - if (p == NULL) return (0); - cp = ((char far *) p) - sizeof(MEMHEADER); - - mp = (MEMHEADER far *) cp; - - if (mp->magic != MAGIC || mp->magic2 != MAGIC2) { - assert (mp->magic == MAGIC); - assert (mp->magic2 == MAGIC2); - return (0); - } - - return (mp->size); -} - - -#if 0 -MemPtr -MemDup (void far *p) -{ - unsigned int len; - void far *p1; - - len = MgetBlkSize (p); - p1 = MemAlloc (len); - if (p1 != NULL) - _fmemcpy(p1, p, len); - - return (p1); -} - - -void -MemoryStatistics (long int *allocated, long int *used, long int *overhead) -{ - MEMPAGEHEADER far *p; - - *allocated = *used = *overhead = 0L; - - for (p = MemHeader.pages; p != NULL; p = p->next) { - *allocated += p->size; - *used += p->used; - *overhead += p->overhead; - } -} -#endif - - -void -MemFreeAll (void) -{ - MEMPAGEHEADER far *p, far *p1; - - for (p = MemHeader.pages; p != NULL; ) { - p1 = p->next; - GlobalUnlock (p->handle); - GlobalFree (p->handle); - p = p1; - } - - MemHeader.pages = NULL; - MemHeader.nr_pages = 0; -} - - -#ifdef MEM_DEBUG - -/* For debugging purposes... not very pretty */ - -void PrintMemoryChains(void) -{ - MEMPAGEHEADER far *p; - MEMHEADER far *mp; - char far *cp; - char buffer[100]; - - /* Block already large enough? */ - - - for (p = MemHeader.pages; p != NULL; p = p->next) { - for (mp = p->data; mp != NULL; mp = mp->next) { - fprintf (MemDebugFile, "%Fp | %u | %s", mp, mp->size, mp->allocated ? "Alloc" : "Free"); - } - } -} - -#endif /* DEBUG */ - - - -#else /* !SEGHEAP. Old version, not used. */ - - - - - - - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * - * Direct memory allocation - * - *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ - -/* - * This following implementation allocates large memory blocks directly - * from global memory and small memory blocks from the local heap. The - * problem with this method is that pine's local heap is quite small - * so most of the memory ends up comming from the global heap. - */ - - -#define GUARD_LOW0 0xbbbb -#define GUARD_LOW 0x9999 -#define GUARD_HIGH 0xaaaaaaaa - -#define SMALL_MEM_BOUNDRY 32 - -#define HEAP_SIZE 32000 - - -/* Memory block header. Placed at beginning of each allocated block. */ -typedef struct { /*size len */ - WORD guard0; /* 00 - 02 */ - HGLOBAL handle; /* 02 - 02 */ - short globalBlk; /* 04 - 02 */ - MemSize size; /* 06 - 04 */ - WORD id; /* 0A - 02 */ - WORD guard1; /* 0C - 02 */ -} MemBlk; /* Total size: 0E */ - -typedef MemBlk __far * MemBlkPtr; - - -/* Memory high guard tailer. Placed at end of each allocated block. */ -typedef struct { - unsigned long guard1; -} MemHighGuard; - -typedef MemHighGuard __far *MemHighGuardPtr; - - -/* - * Memory allocation globals. - */ -LOCAL WORD MemID = 0; /* Keep track of ID. */ -LOCAL unsigned long MemLocalFails = 0; -LOCAL BOOL MemLocalFull = FALSE; /* True when local heap full*/ -#ifdef MEM_DEBUG -LOCAL unsigned long MemInUse = 0; /* Total bytes in use. */ -LOCAL unsigned long MemInUseMax = 0; /* max in use at one time. */ -LOCAL unsigned long SmallMemInUse = 0; -LOCAL unsigned long SmallMemInUseMax = 0; -#endif /* MEM_DEBUG */ - - - -/* - * Allocate a memory block. - * The file and line indicate where we are called from (for debugging) - * but in pine these mostly point to a bottel neck routine and are - * useless. - */ -MemPtr -_MemAlloc (MemSize size, char __far * file, int line) -{ - MemBlkPtr pBlk; - MemHighGuardPtr pHG; - HGLOBAL hBlk; - HLOCAL hLBlk; - UINT totalSize; - BYTE __far * pb; - - assert (size <= MEM_BLOCK_SIZE_MAX); - - - /* - * Calculate total size we need to allocate. - */ - totalSize = (UINT)size + sizeof (MemBlk) + sizeof (MemHighGuard); - - - pBlk = NULL; - - /* - * If it's a small block and the local heap is not full, try - * allocating from the local heap. - */ - if (size <= SMALL_MEM_BOUNDRY && !MemLocalFull) { - - /* Allocate block from local storage. */ - hLBlk = LocalAlloc (LMEM_MOVEABLE, totalSize); - if (hLBlk != NULL) { - - /* Lock block and dereference. */ - pBlk = (MemBlkPtr) LocalLock (hLBlk); - if (pBlk != NULL) { - pBlk->handle = hLBlk; - pBlk->globalBlk = FALSE; - } - else - LocalFree (hLBlk); - } - else { - ++MemLocalFails; - MemLocalFull = TRUE; -#ifdef MEM_DEBUG - if (MemDebugLevel >= MEM_DEBUG_LEVEL) - fprintf (MemDebugFile, "Local Memory alloc failed, %lu fails, %lu bytes in use\n", - MemLocalFails, SmallMemInUse); -#endif - } - } - - - /* - * If it is a large block, or local alloc failed, we allocate from - * global space. - */ - if (pBlk == NULL) { - - /* Allocate block from global storage. */ - hBlk = GlobalAlloc (GMEM_MOVEABLE, totalSize); - if (hBlk == NULL) - return (NULL); - - - /* Lock block and dereference. */ - pBlk = (MemBlkPtr) GlobalLock (hBlk); - if (pBlk == NULL) { - GlobalFree (hBlk); - return (NULL); - } - pBlk->handle = hBlk; - pBlk->globalBlk = TRUE; - } - - - - /* Fill rest of header. */ - pBlk->guard0 = GUARD_LOW0; - pBlk->size = size; - pBlk->id = ++MemID; - pBlk->guard1 = GUARD_LOW; - - - /* Find address that will be returned to caller. */ - pb = (BYTE __far *) (pBlk + 1); - - - /* Find high guard and fill. */ - pHG = (MemHighGuardPtr) (pb + size); - pHG->guard1 = GUARD_HIGH; - - - /* Debugging info... */ -#ifdef MEM_DEBUG - if (MemDebugLevel >= MEM_DEBUG_LEVEL) { - if( !file ) file = "??"; - fprintf (MemDebugFile, "MemAlloc: addr(%lx) id(%u) size(%ld) global(%d)\n", - pb, pBlk->id, (long)size, pBlk->globalBlk); - fflush (MemDebugFile); - } - MemInUse += totalSize; - if (MemInUse > MemInUseMax) - MemInUseMax = MemInUse; - if (size <= SMALL_MEM_BOUNDRY) { - SmallMemInUse += totalSize; - if (SmallMemInUse > SmallMemInUseMax) - SmallMemInUseMax = SmallMemInUse; - } -#endif /* MEM_DEBUG */ - - - return ((MemPtr) pb); -} - - - - -/* - * Free a block. - */ -int -_MemFree (MemPtr block, char __far *file, int line) -{ - MemBlkPtr pBlk; - MemHighGuardPtr pHG; - HGLOBAL hBlk; - HLOCAL hLBlk; - BOOL brc; - UINT totalSize; - - if (block == NULL) - return (0); - - - /* Find header and high guard and check them. */ - pBlk = ((MemBlkPtr)block) - 1; - pHG = (MemHighGuardPtr) ((char __far *)block + pBlk->size); - - totalSize = pBlk->size + sizeof (MemBlk) + sizeof (MemHighGuard); - - /* If these changed them someone wrote where the should not have. */ - assert (pBlk->guard0 == GUARD_LOW0); - assert (pBlk->guard1 == GUARD_LOW); - assert (pHG->guard1 == GUARD_HIGH); - - - -#ifdef MEM_DEBUG - /* Deubgging info... */ - if (MemDebugLevel >= MEM_DEBUG_LEVEL) { - if (pBlk->size <= SMALL_MEM_BOUNDRY && - SmallMemInUse == SmallMemInUseMax) - fprintf (MemDebugFile, "Small memory usage is up to %lu\n", SmallMemInUseMax); - if (MemInUse == MemInUseMax) - fprintf (MemDebugFile, "Memory usage is up to %lu\n", MemInUseMax); - } - MemInUse -= totalSize; - if (pBlk->size <= SMALL_MEM_BOUNDRY) - SmallMemInUse -= totalSize; - if (MemDebugLevel >= MEM_DEBUG_LEVEL) { - fprintf (MemDebugFile, "MemFree: addr(%lx) id(%u)\n", - block, pBlk->id); - fflush (MemDebugFile); - } -#endif /* MEM_DEBUG */ - - - - /* - * Header indicates which block it came from - */ - if (!pBlk->globalBlk) { - /* Unlock block */ - hLBlk = pBlk->handle; - brc = LocalUnlock (hLBlk); - assert (!brc); - - /* And free block. */ - hLBlk = LocalFree (hLBlk); - assert (hLBlk == NULL); - MemLocalFull = FALSE; - } - else { - /* Unlock block */ - hBlk = pBlk->handle; - brc = GlobalUnlock (hBlk); - assert (!brc); - - /* And free block. */ - hBlk = GlobalFree (hBlk); - assert (hBlk == NULL); - } - return (0); -} - - - - -/* - * Reallocate a memory block. Simplistic approach. - */ -MemPtr -_MemRealloc (MemPtr block, MemSize size, char __far * file, int line) -{ - MemPtr newBlock; - - - newBlock = MemAlloc (size); - if (newBlock == NULL) - return (NULL); - - if (block != NULL) { - _fmemcpy (newBlock, block , (size_t)MIN (size, MemBlkSize (block))); - MemFree (block); - } - - return (newBlock); -} - - - -/* - * Return the size of a memory block - */ -MemSize -MemBlkSize (MemPtr block) -{ - MemBlkPtr pBlk; - - if (block == NULL) return (0); - pBlk = ((MemBlkPtr)block) - 1; - assert (pBlk->guard1 == GUARD_LOW); - - return (pBlk->size); -} - - -#ifdef MEM_DEBUG -struct testblock { - struct testblock __far * prev; - HLOCAL h; -}; - - - -void -MemATest (void) -{ - void __near *n; - struct testblock __far *p; - struct testblock __far *pnew; - HLOCAL hl; - int bcount; - UINT segment, start, end; - void __far *f; - HGLOBAL hg; - DWORD dw; - LOCALINFO li; - UINT DataSeg; - -#if 0 - hg = GlobalAlloc (GMEM_FIXED, HEAP_SIZE); /* Allocate global block */ - if (hg == NULL) - return; - f = GlobalLock (hg); /* Lock and get pointer. */ - if (f == NULL) - goto Fail1; - segment = (UINT) GET_SEGMENT (f); /* Get segment and offsets. */ - start = (UINT) GET_OFFSET (f); - end = start + HEAP_SIZE - 1; - start += 16; - if (!LocalInit (segment, start, end)) /* Init it as the local heap*/ - goto Fail2; -#endif -#if 0 - __asm MOV DataSeg,DS; /* Get current DS. */ - __asm MOV DS,segment; /* Set DS to new heap. */ - hl = LocalAlloc (0, SMALL_MEM_BOUNDRY); /* Now allocate something. */ - __asm MOV DS,DataSeg; /* Restore DS. */ - if (hl == NULL) - return; - n = LocalLock (hl); /* Find where it is. */ - f = (void __far *)n; - segment = GET_SEGMENT(f); /* What Segment. */ - dw = GlobalHandle (segment); - hg = (HGLOBAL) (dw & 0xffff); - if (hg == NULL) - return; - - li.dwSize = sizeof (li); /* What size. */ - if (!LocalInfo (&li, hg)) - return; - - dw = GlobalSize (hg); - f = GlobalLock (hg); - GlobalUnlock (hg); - - LocalUnlock (hl); - LocalFree (hl); - - -#endif - - - - - p = NULL; - pnew = NULL; - bcount = 0; - - do { - hl = LocalAlloc (0, SMALL_MEM_BOUNDRY); - if (hl != NULL) { - ++bcount; - n = LocalLock (hl); - pnew = (struct testblock __far*) n; - pnew->h = hl; - pnew->prev = p; - p = pnew; - } - } while (hl != NULL); - - - if (MemDebugFile != NULL) - fprintf (MemDebugFile, "Allocated %d blocks of size %d\n", - bcount, SMALL_MEM_BOUNDRY); - - while (p != NULL) { - pnew = p->prev; - hl = p->h; - LocalUnlock (hl); - LocalFree (hl); - p = pnew; - } - fflush (MemDebugFile); -#if 0 -Fail2: GlobalUnlock (hg); -Fail1: GlobalFree (hg); -#endif - return; -} -#endif /* MEM_DEBUG */ - -#endif /* ifdef SEGHEAP */ - -#endif /* MSC_MALLOC */ |