mirror of
https://github.com/NishiOwO/JWasm.git
synced 2025-04-21 16:54:39 +00:00
265 lines
7.8 KiB
C
265 lines
7.8 KiB
C
/****************************************************************************
|
|
*
|
|
* This code is Public Domain.
|
|
*
|
|
* ========================================================================
|
|
*
|
|
* Description: Memory allocation routines.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#if defined(__UNIX__) && defined(__GNUC__)
|
|
#include <sys/mman.h>
|
|
#endif
|
|
|
|
#include "globals.h"
|
|
#include "memalloc.h"
|
|
|
|
/* what items are stored in the heap?
|
|
* - symbols + symbol names ( asym, dsym; symbol.c )
|
|
* - macro lines ( StoreMacro(); macro.c )
|
|
* - file names ( CurrFName[]; assemble.c )
|
|
* - temp items + buffers ( omf.c, bin.c, coff.c, elf.c )
|
|
* - contexts ( reused; context.c )
|
|
* - codeview debug info ( dbgcv.c )
|
|
* - library names ( includelib; directiv.c )
|
|
* - src lines for FASTPASS ( fastpass.c )
|
|
* - fixups ( fixup.c )
|
|
* - hll items (reused; .IF, .WHILE, .REPEAT; hll.c )
|
|
* - one big input buffer ( src line buffer, tokenarray, string buffer; input.c )
|
|
* - src filenames array ( AddFile(); input.c )
|
|
* - line number info ( -Zd, -Zi; linnum.c )
|
|
* - macro parameter array + default values ( macro.c )
|
|
* - prologue, epilogue macro names ??? ( option.c )
|
|
* - dll names ( OPTION DLLIMPORT; option.c )
|
|
* - std queue items ( see queues in struct module_vars; globals.h, queue.c )
|
|
* - renamed keyword queue ( reswords.c )
|
|
* - safeseh queue ( safeseh.c )
|
|
* - segment alias names ( segment.c )
|
|
* - segment stack ( segment.c )
|
|
* - segment buffers ( 1024 for omf, else may be HUGE ) ( segment.c )
|
|
* - segment names for simplified segment directives (simsegm.c )
|
|
* - strings of text macros ( string.c )
|
|
* - struct/union/record member items + default values ( types.c )
|
|
* - procedure prologue argument, debug info ( proc.c )
|
|
*/
|
|
|
|
#if FASTMEM
|
|
|
|
/* FASTMEM is a simple memory alloc approach which allocates chunks of 512 kB
|
|
* and will release it only at MemFini().
|
|
*
|
|
* May be considered to create an additional "line heap" to store lines of
|
|
* loop macros and generated code - since this is hierarchical, a simple
|
|
* Mark/Release mechanism will do the memory management.
|
|
* currently generated code lines are stored in the C heap, while
|
|
* loop macro lines go to the "fastmem" heap.
|
|
*/
|
|
|
|
#define BLKSIZE 0x80000
|
|
|
|
#ifndef __UNIX__
|
|
#if defined(__OS2__)
|
|
#include <os2.h>
|
|
#elif defined(__DJGPP__)
|
|
#include <dpmi.h>
|
|
#else
|
|
#include "win32.h"
|
|
#endif
|
|
#endif
|
|
|
|
struct linked_list {
|
|
struct linked_list *next;
|
|
};
|
|
static struct linked_list *pBase; /* start list of 512 kB blocks; to be moved to ModuleInfo.g */
|
|
static uint_8 *pCurr; /* points into current block; to be moved to ModuleInfo.g */
|
|
static uint_32 currfree; /* free memory left in current block; to be moved to ModuleInfo.g */
|
|
#ifdef DEBUG_OUT
|
|
static int blocks; /* number of blocks allocated so far; to be moved to ModuleInfo.g */
|
|
#endif
|
|
|
|
#if defined(__UNIX__) && defined(__WATCOMC__)
|
|
|
|
#define SYS_mmap 90
|
|
#define SYS_munmap 91
|
|
|
|
uint_32 sys_call1( uint_32 func, uint_32 r_ebx );
|
|
#pragma aux sys_call1 = \
|
|
"int 0x80" \
|
|
parm [eax] [ebx] \
|
|
value [eax];
|
|
|
|
uint_32 sys_call2( uint_32 func, uint_32 r_ebx, uint_32 r_ecx );
|
|
#pragma aux sys_call2 = \
|
|
"int 0x80" \
|
|
parm [eax] [ebx] [ecx] \
|
|
value [eax];
|
|
|
|
struct mmap {
|
|
uint_32 base; /* linear base (or 0) */
|
|
uint_32 size; /* size in bytes */
|
|
uint_32 access; /* 3 = PROT_READ | PROT_WRITE */
|
|
uint_32 flags; /* 0x22 = MAP_PRIVATE | MAP_ANON */
|
|
uint_32 fd; /* should be -1 */
|
|
uint_32 offset; /* ignored */
|
|
};
|
|
static struct mmap mymmap = { 0, 0, 3, 0x22, -1, 0 };
|
|
#endif
|
|
|
|
#ifndef __UNIX__
|
|
#if defined(__OS2__)
|
|
#define BLKALLOC( p, size ) DosAllocMem( (void**)&p, size, PAG_COMMIT|PAG_READ|PAG_WRITE )
|
|
#define BLKFREE( p ) DosFreeMem( p )
|
|
#elif defined(__NT__) || defined(_WIN64)
|
|
#define BLKALLOC( p, size ) p = (uint_8 *)VirtualAlloc( NULL, size, MEM_COMMIT, PAGE_READWRITE )
|
|
#define BLKFREE( p ) VirtualFree( p, 0, MEM_RELEASE )
|
|
#else
|
|
#define BLKALLOC( p, size ) p = malloc( size )
|
|
#define BLKFREE( p ) free( p )
|
|
#endif
|
|
#else
|
|
#if defined(__WATCOMC__)
|
|
#define BLKALLOC( p, size_ ) mymmap.size = size_; \
|
|
p = (uint_8 *)sys_call1( SYS_mmap, (uint_32)&mymmap )
|
|
#define BLKFREE( p ) sys_call2( SYS_munmap, (uint_32)p, 0 )
|
|
#else
|
|
#define BLKALLOC( p, size ) p = (uint_8 *)mmap( 0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0 ); \
|
|
if ( p == MAP_FAILED ) p = NULL
|
|
#define BLKFREE( p ) munmap( (void *)p, 0 )
|
|
#endif
|
|
#endif
|
|
|
|
#endif /* FASTMEM */
|
|
|
|
#ifdef DEBUG_OUT
|
|
static uint_32 memcalls = 0;
|
|
static uint_32 memstart;
|
|
#endif
|
|
|
|
#ifdef TRMEM /* track memory allocation? */
|
|
|
|
#include "trmem.h"
|
|
|
|
extern _trmem_hdl hTrmem;
|
|
#define malloc( x ) _trmem_alloc( x, _trmem_guess_who( &x ), hTrmem )
|
|
#define free( x ) _trmem_free( x, _trmem_guess_who( &x ), hTrmem )
|
|
|
|
#endif
|
|
|
|
void MemInit( void )
|
|
/******************/
|
|
{
|
|
#if FASTMEM
|
|
pBase = NULL;
|
|
currfree = 0;
|
|
DebugCmd( blocks = 0 );
|
|
#endif
|
|
DebugCmd( memstart = memcalls );
|
|
}
|
|
|
|
void MemFini( void )
|
|
/******************/
|
|
{
|
|
|
|
#if FASTMEM
|
|
#ifdef DEBUG_OUT
|
|
if ( Options.quiet == FALSE )
|
|
printf( "memory used: %u kB\n", (blocks * BLKSIZE - currfree) / 1024 );
|
|
#endif
|
|
while ( pBase ) {
|
|
struct linked_list *pNext = pBase->next;
|
|
BLKFREE( pBase );
|
|
pBase = pNext;
|
|
}
|
|
#endif
|
|
#ifdef DEBUG_OUT
|
|
if ( memcalls != memstart )
|
|
printf("still allocated memory blocks : %u\n", memcalls - memstart );
|
|
#endif
|
|
}
|
|
|
|
void *LclAlloc( size_t size )
|
|
/***************************/
|
|
{
|
|
void *ptr;
|
|
|
|
#if FASTMEM
|
|
size = (size + sizeof(void *)-1) & ~(sizeof(void *)-1);
|
|
if ( currfree < size ) {
|
|
DebugMsg(("LclAlloc: new block needed, req. size=%Xh > currfree=%Xh\n", size, currfree ));
|
|
currfree = ( size <= ( BLKSIZE - sizeof( struct linked_list ) ) ? BLKSIZE - sizeof( struct linked_list ) : size );
|
|
BLKALLOC( pCurr, currfree + sizeof( struct linked_list ) );
|
|
if ( !pCurr ) {
|
|
currfree = 0;
|
|
Fatal( OUT_OF_MEMORY );
|
|
}
|
|
((struct linked_list *)pCurr)->next = pBase;
|
|
pBase = (struct linked_list *)pCurr;
|
|
pCurr += sizeof( struct linked_list );
|
|
DebugCmd( blocks++ );
|
|
}
|
|
ptr = pCurr;
|
|
pCurr += size;
|
|
currfree -= size;
|
|
|
|
#else /* ! FASTMEM */
|
|
|
|
ptr = malloc( size );
|
|
#ifdef TRMEM
|
|
DebugMsg1(("LclAlloc(0x%X)=%p cnt=%" I32_SPEC "u\n", size, ptr, ++memcalls ));
|
|
#endif
|
|
if( ptr == NULL ) {
|
|
Fatal( OUT_OF_MEMORY );
|
|
}
|
|
#endif
|
|
return( ptr );
|
|
}
|
|
|
|
#if FASTMEM==0
|
|
void LclFree( void *ptr )
|
|
/***********************/
|
|
{
|
|
if( ptr != NULL ) {
|
|
#ifdef TRMEM
|
|
DebugMsg1(("LclFree(0x%p) cnt=%" I32_SPEC "u\n", ptr, --memcalls ));
|
|
#endif
|
|
free( ptr );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void *MemAlloc( size_t size )
|
|
/***************************/
|
|
{
|
|
void *ptr;
|
|
ptr = malloc( size );
|
|
DebugMsg1(("MemAlloc(0x%X)=%p cnt=%" I32_SPEC "u\n", size, ptr, ++memcalls ));
|
|
if( ptr == NULL ) {
|
|
Fatal( OUT_OF_MEMORY );
|
|
}
|
|
//memset( ptr, 0xff, size );
|
|
return( ptr );
|
|
}
|
|
|
|
void MemFree( void *ptr )
|
|
/***********************/
|
|
{
|
|
DebugMsg1(("MemFree(0x%p) cnt=%" I32_SPEC "u\n", ptr, --memcalls ));
|
|
free( ptr );
|
|
return;
|
|
}
|
|
|
|
#if 0
|
|
void *MemRealloc( void *ptr, size_t size )
|
|
/****************************************/
|
|
{
|
|
void *new;
|
|
|
|
new = realloc( ptr, size );
|
|
if( new == NULL && size != 0 ) {
|
|
Fatal( OUT_OF_MEMORY );
|
|
}
|
|
return( new );
|
|
}
|
|
#endif
|