Windows2003-3790/enduser/netmeeting/av/codecs/dec/dech261/sc_mem.c
2020-09-30 16:53:55 +02:00

448 lines
13 KiB
C

/*
* @DEC_COPYRIGHT@
*/
/*
* HISTORY
* $Log: sc_mem.c,v $
* Revision 1.1.4.2 1996/01/02 18:30:56 Bjorn_Engberg
* Got rid of compiler warnings: Added include files for NT.
* [1996/01/02 15:25:04 Bjorn_Engberg]
*
* Revision 1.1.2.4 1995/09/20 14:59:33 Bjorn_Engberg
* Port to NT
* [1995/09/20 14:41:14 Bjorn_Engberg]
*
* Revision 1.1.2.3 1995/09/14 17:28:09 Bjorn_Engberg
* Ported to NT
* [1995/09/14 17:21:10 Bjorn_Engberg]
*
* Revision 1.1.2.2 1995/05/31 18:07:53 Hans_Graves
* Inclusion in new SLIB location.
* [1995/05/31 16:15:46 Hans_Graves]
*
* Revision 1.1.2.2 1995/05/03 19:12:55 Hans_Graves
* First time under SLIB
* [1995/05/03 19:12:17 Hans_Graves]
*
* Revision 1.1.2.3 1995/04/17 17:46:54 Hans_Graves
* Added ScAlloc2()
* [1995/04/17 17:45:28 Hans_Graves]
*
* Revision 1.1.2.2 1995/04/07 18:40:03 Hans_Graves
* Inclusion in SLIB's Su library
* [1995/04/07 18:39:43 Hans_Graves]
*
* $EndLog$
*/
/*****************************************************************************
** Copyright (c) Digital Equipment Corporation, 1993 **
** **
** All Rights Reserved. Unpublished rights reserved under the copyright **
** laws of the United States. **
** **
** The software contained on this media is proprietary to and embodies **
** the confidential technology of Digital Equipment Corporation. **
** Possession, use, duplication or dissemination of the software and **
** media is authorized only pursuant to a valid written license from **
** Digital Equipment Corporation. **
** **
** RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the U.S. **
** Government is subject to restrictions as set forth in Subparagraph **
** (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. **
******************************************************************************/
/*-------------------------------------------------------------------------
** Modification History: sc_mem.c
** 05-29-93 Victor Bahl Paged aligned malloc and free
** 12-07-93 PSG Added error reporting code
** 03-15-95 HWG Moved to Su library, Added SuAlloc & SuFree
** 04-04-97 HWG With WIN32 use LocalAlloc and LocalFree in
** place of malloc and free
** Added ScCalloc function.
** 04-15-97 HWG Added memory linked list to help track leaks
** Fixed potential initalization bug in linked
** list used to track ScPaMalloc's
--------------------------------------------------------------------------*/
/*
#define _SLIBDEBUG_
*/
#include <stdio.h> /* NULL */
#include <sys/types.h>
#ifdef WIN32
#include <windows.h>
#include <stdlib.h>
#include <malloc.h>
#endif /* WIN32 */
#include "SC.h"
#include "SC_err.h"
#ifdef _SLIBDEBUG_
#include "sc_debug.h"
#define _DEBUG_ 0 /* detailed debuging statements */
#define _VERBOSE_ 0 /* show progress */
#define _VERIFY_ 1 /* verify correct operation */
#define _WARN_ 1 /* warnings about strange behavior */
/* keep a linked list to ttrack memory leaks */
typedef struct memblock_s {
void *ptr;
dword size;
dword counter;
char desc[15];
struct memblock_s *next;
} memblock_t;
static memblock_t *_blocklist=NULL;
static _blockcounter=0;
static _memused=0;
void scMemAddWatch(void *ptr, dword size, char *desc)
{
memblock_t *pblock;
#if defined(WIN32)
pblock = (void *)LocalAlloc(LPTR, sizeof(memblock_t));
#else
pblock = (void *)malloc(sizeof(memblock_t));
#endif
_memused+=size;
if (pblock)
{
pblock->ptr=ptr;
pblock->next=_blocklist;
pblock->size=size;
pblock->counter=_blockcounter;
if (desc==NULL)
pblock->desc[0]=0;
else
{
int i;
for (i=0; desc[i] && i<14; i++)
pblock->desc[i]=desc[i];
pblock->desc[i]=0;
}
_blocklist=pblock;
_blockcounter++;
}
}
ScBoolean_t scMemRemoveWatch(void *ptr)
{
memblock_t *plastblock=NULL, *pblock=_blocklist;
while (pblock)
{
if (pblock->ptr==ptr) /* remove from list */
{
if (plastblock==NULL) /* beginning of linked list */
_blocklist=pblock->next;
else
plastblock->next=pblock->next;
_memused-=pblock->size;
#ifdef WIN32
LocalFree(pblock);
#else
free(pblock);
#endif
if (_blocklist==NULL) /* all memory freed, reset counter */
_blockcounter=0;
return(TRUE);
}
plastblock=pblock;
pblock=pblock->next;
}
return(FALSE);
}
dword scMemDump()
{
memblock_t *plastblock=NULL, *pblock=_blocklist;
ScDebugPrintf(NULL, "scMemDump: memused=%ld\n", _memused);
while (pblock)
{
ScDebugPrintf(NULL, " ptr=%p counter=%ld size=%ld desc=%s\n",
pblock->ptr, pblock->counter, pblock->size, pblock->desc);
pblock=pblock->next;
}
return(_memused);
}
#endif
#ifdef WIN32
int getpagesize()
{
SYSTEM_INFO sysInfo;
static int pagesize = 0 ;
if( pagesize == 0 ) {
GetSystemInfo(&sysInfo);
pagesize = (int)sysInfo.dwPageSize;
}
return pagesize ;
}
#define bzero(_addr_,_len_) memset(_addr_,0,_len_)
#endif
/*------------------------------------------------------------------------
Simple Memory Allocation
-------------------------------------------------------------------------*/
/*
** Name: ScAlloc
** Purpose: Allocate number of bytes of memory.
**
*/
void *ScAlloc(unsigned long bytes)
{
void *ptr;
#ifdef MACINTOSH
ptr = NewPtr(bytes);
#elif MSC60
ptr = (void FAR *) _fmalloc((unsigned int)bytes); /* far memory */
#elif defined(WIN32)
ptr = (void *)LocalAlloc(LPTR, bytes);
#else
ptr = (void *)malloc(bytes);
#endif
_SlibDebug(ptr, scMemAddWatch(ptr, bytes, NULL) );
_SlibDebug(_DEBUG_, ScDebugPrintf(NULL, "ScAlloc(%ld) returns %p\n",bytes,ptr) );
return(ptr);
}
/*
** Name: ScCalloc
** Purpose: Allocate number of bytes of memory and zero it out.
**
*/
void *ScCalloc(unsigned long bytes)
{
void *ptr = ScAlloc(bytes);
if (ptr != NULL)
{
#ifdef MSC60
_fmemset(ptr, 0, (unsigned int)bytes);
#else
memset(ptr, 0, bytes);
#endif
}
_SlibDebug(_DEBUG_, ScDebugPrintf(NULL, "ScCalloc(%ld) returns %p\n",bytes,ptr) );
return(ptr);
}
/*
** Name: ScAlloc2
** Purpose: Allocate number of bytes of memory equal to "bytes".
** Takes an extra argument "name" which identifies the block
** (used for debugging).
*/
void *ScAlloc2(unsigned long bytes, char *desc)
{
void *ptr;
ptr = ScAlloc(bytes);
#ifdef _SLIBDEBUG_
if (_blocklist) /* copy description to leak tracking info */
{
int i;
for (i=0; desc[i] && i<14; i++)
_blocklist->desc[i]=desc[i];
_blocklist->desc[i]=0;
}
#endif
_SlibDebug(_DEBUG_,
ScDebugPrintf(NULL, "ScAlloc(%ld, %s) returns %p\n",bytes,desc,ptr) );
return(ptr);
}
/*
** Name: ScFree
** Purpose: Free memory pointed to by "*ptr_addr"
**
*/
void ScFree(void *ptr)
{
_SlibDebug(_DEBUG_, ScDebugPrintf(NULL, "ScFree(%p)\n", ptr) );
_SlibDebug(ptr, scMemRemoveWatch(ptr) );
if (ptr != NULL)
{
#ifdef MACINTOSH
DisposPtr(ptr);
#elif defined(WIN32)
#ifdef _SLIBDEBUG_
_SlibDebug(LocalFree(ptr)!=NULL, ScDebugPrintf(NULL, "ScFree(%p) failed\n", ptr) );
#else
LocalFree(ptr);
#endif
#else
free(ptr);
#endif
}
}
/*
** Name: ScMemCheck
** Purpose: Check block of memory all equal to a single byte,
** else return FALSE
*/
int ScMemCheck(char *array, int test, int num)
{
int i=0;
/* 'test' is only tested as a char (bottom 8 bits) */
while (array[i] == test && i<num)
i++;
if (i==num)
return TRUE;
else
return FALSE;
}
/*------------------------------------------------------------------------
Paged aligned malloc() and free()
-------------------------------------------------------------------------*/
/*
** This structure is used by the page align malloc/free support code.
** These "working sets" will contain the malloc-ed address and the
** page aligned address for the free*() call.
*/
typedef struct mpa_ws_s
{
char *palign_addr; /* the page aligned address that's used */
char *malloc_addr; /* the malloc-ed address to free */
struct mpa_ws_s *next; /* for the next on the list */
} mpa_ws_t;
/*
** Initialized and uninitialized data.
*/
static mpa_ws_t *mpa_qhead=NULL; /* local Q head for the malloc stuctures */
/*
** Name: ScPaMalloc
** Purpose: Allocate Paged Alligned Memory
** This routine allocates and returns to the caller a system
** page aligned buffer. Enough space will be added, one more
** page, to allow the pointers to be adjusted to the next page
** boundry. A local linked list will keep copies of the original
** and adjusted addresses. This list will be used by sv_PaFree()
** to free the correct buffer.
**
*/
char *ScPaMalloc(int size)
{
mpa_ws_t *ws; /* pointer for the working set */
ULONG_PTR tptr; /* to store pointer temp for bit masking */
int PageSize = getpagesize(); /* system's page size */
/*
** The space for the working set structure that will go on the queue
** is allocated first.
*/
if ((ws = (mpa_ws_t *)ScAlloc(sizeof(mpa_ws_t))) == (mpa_ws_t *)NULL)
return( (char *)NULL );
/*
** Using the requested size, from the argument list, and the page size
** from the system, allocate enough space to page align the requested
** buffer. The original request will have the space of one system page
** added to it. The pointer will be adjusted.
*/
ws->malloc_addr = (char *)ScAlloc(size + PageSize);
if (ws->malloc_addr == (char *)NULL)
{
ScFree(ws); /* not going to be used */
return((char *)NULL); /* signal the failure */
} else
(void) bzero (ws->malloc_addr, (size + PageSize));
/*
** Now using the allocated space + 1 page, adjust the pointer to
** point to the next page boundry.
*/
ws->palign_addr = ws->malloc_addr + PageSize; /* to the next page */
/*
** Using the page size and subtracting 1 to get a bit mask, mask off
** the low order "page offset" bits to get the aligned address. Now the
** aligned pointer will contain the address of the next page with enough
** space to hold the users requested size.
*/
tptr = (ULONG_PTR)ws->palign_addr; /* copy to local int */
tptr &= (ULONG_PTR)(~(PageSize - 1)); /* Mask addr bit to the */
ws->palign_addr = (char *)tptr; /* put back the address */
/*
** Put the working set onto the linked list so that the original
** malloc-ed buffer can be freeed when the user program is done with it.
*/
ws->next=mpa_qhead;
mpa_qhead=ws; /* just put it at the head */
/*
** Now return the aligned address to the caller.
*/
return((char *)ws->palign_addr);
}
/*
** Name: ScPaFree
** Purpose: This is a local free routine to return to the system a previously
** alloc-ed buffer. A local linked list keeps copies of the original
** and adjusted addresses. This list is used by this routine to free
** the correct buffer.
*/
void ScPaFree (void *pa_addr)
{
mpa_ws_t *p, *q; /* walkers for the malloc list */
/*
** Walk along the malloc-ed memory linked list, watch for a match
** on the page aligned address. If a match is found break out of the
** loop.
*/
p = mpa_qhead; /* set the pointers */
q = NULL;
while (p != NULL)
{
if (p->palign_addr == pa_addr) /* found the buffer */
break;
q = p; /* save current */
p = p->next; /* get next */
}
_SlibDebug(_WARN_ && p==NULL,
ScDebugPrintf(NULL, "ScPaFree(%p) Illegal pointer\n", pa_addr) );
/*
** After falling out of the loop the pointers are at the place where
** some work has to be done, (this could also be at the beginning).
** If a match is found call the free() routine to return the buffer, if
** the loop fell off the end just return.
*/
if (p != NULL)
{
/*
** Where on the list is it, check for making it empty.
*/
if (q == NULL) /* at the front */
mpa_qhead = p->next; /* pop off front */
else /* inside the list */
q->next = p->next; /* pop it */
ScFree(p->malloc_addr); /* free the malloc-ed addr */
/*
** Now free up the working set, it is not needed any more.
*/
ScFree(p);
}
}