📄 memalloc.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 06/05/06 */
/* */
/* MEMORY MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Memory allocation routines. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* Brian L. Donnell */
/* */
/* Revision History: */
/* */
/* 6.24: Removed HaltExecution check from the */
/* EnvReleaseMem function. DR0863 */
/* */
/* Renamed BOOLEAN macro type to intBool. */
/* */
/* Corrected code to remove compiler warnings. */
/* */
/*************************************************************/
#define _MEMORY_SOURCE_
#include <stdio.h>
#define _STDIO_INCLUDED_
#include "setup.h"
#include "constant.h"
#include "envrnmnt.h"
#include "memalloc.h"
#include "router.h"
#include "utility.h"
#include <stdlib.h>
#if IBM_TBC
#include <alloc.h>
#endif
#if IBM_MSC || IBM_ICB
#include <malloc.h>
#endif
#if IBM_ZTC || IBM_SC
#include <dos.h>
#endif
#define STRICT_ALIGN_SIZE sizeof(double)
#define SpecialMalloc(sz) malloc((STD_SIZE) sz)
#define SpecialFree(ptr) free(ptr)
/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/
#if BLOCK_MEMORY
static int InitializeBlockMemory(void *,unsigned int);
static int AllocateBlock(void *,struct blockInfo *,unsigned int);
static void AllocateChunk(void *,struct blockInfo *,struct chunkInfo *,unsigned int);
#endif
/********************************************/
/* InitializeMemory: Sets up memory tables. */
/********************************************/
globle void InitializeMemory(
void *theEnv)
{
int i;
AllocateEnvironmentData(theEnv,MEMORY_DATA,sizeof(struct memoryData),NULL);
MemoryData(theEnv)->OutOfMemoryFunction = DefaultOutOfMemoryFunction;
MemoryData(theEnv)->MemoryTable = (struct memoryPtr **)
malloc((STD_SIZE) (sizeof(struct memoryPtr *) * MEM_TABLE_SIZE));
if (MemoryData(theEnv)->MemoryTable == NULL)
{
PrintErrorID(theEnv,"MEMORY",1,TRUE);
EnvPrintRouter(theEnv,WERROR,"Out of memory.\n");
EnvExitRouter(theEnv,EXIT_FAILURE);
}
for (i = 0; i < MEM_TABLE_SIZE; i++) MemoryData(theEnv)->MemoryTable[i] = NULL;
}
/***************************************************/
/* genalloc: A generic memory allocation function. */
/***************************************************/
globle void *genalloc(
void *theEnv,
unsigned int size)
{
char *memPtr;
#if BLOCK_MEMORY
memPtr = (char *) RequestChunk(theEnv,size);
if (memPtr == NULL)
{
EnvReleaseMem(theEnv,(long) ((size * 5 > 4096) ? size * 5 : 4096),FALSE);
memPtr = (char *) RequestChunk(theEnv,size);
if (memPtr == NULL)
{
EnvReleaseMem(theEnv,-1L,TRUE);
memPtr = (char *) RequestChunk(theEnv,size);
while (memPtr == NULL)
{
if ((*MemoryData(theEnv)->OutOfMemoryFunction)(theEnv,(unsigned long) size))
return(NULL);
memPtr = (char *) RequestChunk(theEnv,size);
}
}
}
#else
memPtr = (char *) malloc((STD_SIZE) size);
if (memPtr == NULL)
{
EnvReleaseMem(theEnv,(long) ((size * 5 > 4096) ? size * 5 : 4096),FALSE);
memPtr = (char *) malloc((STD_SIZE) size);
if (memPtr == NULL)
{
EnvReleaseMem(theEnv,-1L,TRUE);
memPtr = (char *) malloc((STD_SIZE) size);
while (memPtr == NULL)
{
if ((*MemoryData(theEnv)->OutOfMemoryFunction)(theEnv,(unsigned long) size))
return(NULL);
memPtr = (char *) malloc((STD_SIZE) size);
}
}
}
#endif
MemoryData(theEnv)->MemoryAmount += (long) size;
MemoryData(theEnv)->MemoryCalls++;
return((void *) memPtr);
}
/***********************************************/
/* DefaultOutOfMemoryFunction: Function called */
/* when the KB runs out of memory. */
/***********************************************/
#if IBM_TBC
#pragma argsused
#endif
globle int DefaultOutOfMemoryFunction(
void *theEnv,
unsigned long size)
{
#if MAC_MCW || IBM_MCW || MAC_XCD
#pragma unused(size)
#endif
PrintErrorID(theEnv,"MEMORY",1,TRUE);
EnvPrintRouter(theEnv,WERROR,"Out of memory.\n");
EnvExitRouter(theEnv,EXIT_FAILURE);
return(TRUE);
}
/***********************************************************/
/* EnvSetOutOfMemoryFunction: Allows the function which is */
/* called when the KB runs out of memory to be changed. */
/***********************************************************/
globle int (*EnvSetOutOfMemoryFunction(void *theEnv,int (*functionPtr)(void *,unsigned long)))(void *,unsigned long)
{
int (*tmpPtr)(void *,unsigned long);
tmpPtr = MemoryData(theEnv)->OutOfMemoryFunction;
MemoryData(theEnv)->OutOfMemoryFunction = functionPtr;
return(tmpPtr);
}
/****************************************************/
/* genfree: A generic memory deallocation function. */
/****************************************************/
globle int genfree(
void *theEnv,
void *waste,
unsigned size)
{
#if BLOCK_MEMORY
if (ReturnChunk(theEnv,waste,size) == FALSE)
{
PrintErrorID(theEnv,"MEMORY",2,TRUE);
EnvPrintRouter(theEnv,WERROR,"Release error in genfree.\n");
return(-1);
}
#else
free(waste);
#endif
MemoryData(theEnv)->MemoryAmount -= (long) size;
MemoryData(theEnv)->MemoryCalls--;
return(0);
}
/******************************************************/
/* genrealloc: Simple (i.e. dumb) version of realloc. */
/******************************************************/
globle void *genrealloc(
void *theEnv,
void *oldaddr,
unsigned oldsz,
unsigned newsz)
{
char *newaddr;
unsigned i;
unsigned limit;
newaddr = ((newsz != 0) ? (char *) gm2(theEnv,newsz) : NULL);
if (oldaddr != NULL)
{
limit = (oldsz < newsz) ? oldsz : newsz;
for (i = 0 ; i < limit ; i++)
{ newaddr[i] = ((char *) oldaddr)[i]; }
for ( ; i < newsz; i++)
{ newaddr[i] = '\0'; }
rm(theEnv,(void *) oldaddr,oldsz);
}
return((void *) newaddr);
}
/************************************************/
/* genlongalloc: Allocates blocks of memory for */
/* sizes expressed using long integers. */
/************************************************/
#if IBM_TBC
#pragma warn -rch
#pragma warn -ccc
#endif
globle void *genlongalloc(
void *theEnv,
unsigned long size)
{
#if (! MAC) && (! IBM_TBC) && (! IBM_MSC) && (! IBM_ICB) && (! IBM_ZTC) && (! IBM_SC) && (! IBM_MCW)
unsigned int test;
#else
void *memPtr;
#endif
#if BLOCK_MEMORY
struct longMemoryPtr *theLongMemory;
#endif
if (sizeof(int) == sizeof(long))
{ return(genalloc(theEnv,(unsigned) size)); }
#if (! MAC) && (! IBM_TBC) && (! IBM_MSC) && (! IBM_ICB) && (! IBM_ZTC) && (! IBM_SC) && (! IBM_MCW)
test = (unsigned int) size;
if (test != size)
{
PrintErrorID(theEnv,"MEMORY",3,TRUE);
EnvPrintRouter(theEnv,WERROR,"Unable to allocate memory block > 32K.\n");
EnvExitRouter(theEnv,EXIT_FAILURE);
}
return((void *) genalloc(theEnv,(unsigned) test));
#else
#if BLOCK_MEMORY
size += sizeof(struct longMemoryPtr);
#endif
memPtr = (void *) SpecialMalloc(size);
if (memPtr == NULL)
{
EnvReleaseMem(theEnv,(long) ((size * 5 > 4096) ? size * 5 : 4096),FALSE);
memPtr = (void *) SpecialMalloc(size);
if (memPtr == NULL)
{
EnvReleaseMem(theEnv,-1L,TRUE);
memPtr = (void *) SpecialMalloc(size);
while (memPtr == NULL)
{
if ((*MemoryData(theEnv)->OutOfMemoryFunction)(theEnv,size))
return(NULL);
memPtr = (void *) SpecialMalloc(size);
}
}
}
MemoryData(theEnv)->MemoryAmount += (long) size;
MemoryData(theEnv)->MemoryCalls++;
#if BLOCK_MEMORY
theLongMemory = (struct longMemoryPtr *) memPtr;
theLongMemory->next = MemoryData(theEnv)->TopLongMemoryPtr;
theLongMemory->prev = NULL;
theLongMemory->size = (long) size;
memPtr = (void *) (theLongMemory + 1);
#endif
return(memPtr);
#endif
}
#if IBM_TBC
#pragma warn +rch
#pragma warn +ccc
#endif
/*********************************************/
/* genlongfree: Returns blocks of memory for */
/* sizes expressed using long integers. */
/*********************************************/
#if IBM_TBC
#pragma warn -rch
#pragma warn -ccc
#endif
globle int genlongfree(
void *theEnv,
void *ptr,
unsigned long size)
{
#if (! MAC) && (! IBM_TBC) && (! IBM_MSC) && (! IBM_ICB) && (! IBM_ZTC) && (! IBM_SC) && (! IBM_MCW)
unsigned int test;
#endif
#if BLOCK_MEMORY
struct longMemoryPtr *theLongMemory;
#endif
if (sizeof(unsigned int) == sizeof(unsigned long))
{ return(genfree(theEnv,(void *) ptr,(unsigned) size)); }
#if (! MAC) && (! IBM_TBC) && (! IBM_MSC) && (! IBM_ICB) && (! IBM_ZTC) && (! IBM_SC) && (! IBM_MCW)
test = (unsigned int) size;
if (test != size) return(-1);
return(genfree(theEnv,(void *) ptr,(unsigned) test));
#endif
#if BLOCK_MEMORY
size += sizeof(struct longMemoryPtr);
theLongMemory = ((struct longMemoryPtr *) ptr) - 1;
if (theLongMemory->prev == NULL)
{
MemoryData(theEnv)->TopLongMemoryPtr = MemoryData(theEnv)->TopLongMemoryPtr->next;
MemoryData(theEnv)->TopLongMemoryPtr->prev = NULL;
}
else
{
theLongMemory->prev->next = theLongMemory->next;
if (theLongMemory->next != NULL)
{ theLongMemory->next->prev = theLongMemory->next; }
}
#endif
#if MAC || IBM_ICB || IBM_MCW
MemoryData(theEnv)->MemoryAmount -= (long) size;
MemoryData(theEnv)->MemoryCalls--;
SpecialFree(ptr);
return(0);
#endif
#if IBM_TBC || IBM_ZTC || IBM_SC
MemoryData(theEnv)->MemoryAmount -= size;
MemoryData(theEnv)->MemoryCalls--;
SpecialFree(ptr);
return(0);
#endif
#if IBM_MSC
MemoryData(theEnv)->MemoryAmount -= size;
MemoryData(theEnv)->MemoryCalls--;
SpecialFree(ptr);
return(0);
#endif
}
#if IBM_TBC
#pragma warn +rch
#pragma warn +ccc
#endif
/********************************/
/* EnvMemUsed: C access routine */
/* for the mem-used command. */
/********************************/
globle long int EnvMemUsed(
void *theEnv)
{
return(MemoryData(theEnv)->MemoryAmount);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -