summaryrefslogtreecommitdiff
path: root/pico/msmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'pico/msmem.c')
-rw-r--r--pico/msmem.c1301
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 */