campo-sirio/cb5/m4memory.c

824 lines
17 KiB
C
Raw Normal View History

/* m4memory.c (c)Copyright Sequiter Software Inc., 1990-1994. All rights reserved. */
#ifdef S4OS2
#ifdef __DLL__
#define INCL_DOSMEMMGR
#endif
#endif
#include "d4all.h"
#ifdef S4VB_DOS
#include "malloc.h"
#endif
#ifndef S4UNIX
#ifdef __TURBOC__
#pragma hdrstop
#endif
#endif
#ifdef S4OS2
#ifdef __DLL__
#include <bsememf.h>
#endif
#endif
#ifdef S4MEM_PRINT
int v4print = 0 ; /* if v4print == 0 then stdout, else stdprn */
#endif
#define mem4num_types 10
typedef struct
{
LINK4 link ;
MEM4 types[mem4num_types] ;
} MEMORY4GROUP ;
static LIST4 avail = { 0, 0, 0 } ; /* A list of available MEM4 entries */
static LIST4 used = { 0, 0, 0 } ; /* A list of used MEM4 entries */
static LIST4 groups = { 0, 0, 0 } ; /* A list of Allocated MEM4 groups */
#ifdef S4OS2
#ifdef S4OS2SEM
int mem4start( CODE4 *c4 )
{
APIRET rc ;
#ifdef S4DEBUG
if ( c4 == 0 )
return e4( c4, e4info, "OS/2 Semaphore Failure" ) ;
#endif
rc = DosRequestMutexSem( c4->hmtx_mem, -1 ) ;
if ( rc != 0 )
return e4( c4, e4info, "OS/2 Semaphore Failure" ) ;
return 0 ;
}
void mem4stop( CODE4 *c4 )
{
#ifdef S4DEBUG
if ( c4 == 0 )
{
e4( c4, e4info, "OS/2 Semaphore Failure" ) ;
return ;
}
#endif
DosReleaseMutexSem( c4->hmtx_mem ) ;
}
#endif
#endif
#ifdef S4DEBUG
static char **mem4test_pointers ;
static int mem4num_pointer = -1 ;
static int mem4num_used = 0 ;
#ifdef S4UNIX
#define mem4extra_chars 12
#else
#define mem4extra_chars 10
#endif
#define mem4extra_tot (mem4extra_chars*2 + sizeof(unsigned))
#define mem4check_char 0x55
/* Returns the pointer to be returned; is passed the pointer allocated by malloc ... */
static char *mem4fix_pointer( char *start_ptr, unsigned large_len )
{
char *return_ptr ;
unsigned pos ;
memset( start_ptr, mem4check_char, mem4extra_chars ) ;
return_ptr = start_ptr + mem4extra_chars ;
memcpy( return_ptr, (void *)&large_len, sizeof(large_len) ) ;
pos = large_len - mem4extra_chars ;
memset( start_ptr+ pos, mem4check_char, mem4extra_chars ) ;
return return_ptr + sizeof(unsigned) ;
}
/* Returns the pointer allocated by malloc; */
/* passed by pointer returned by 'mem4fix_pointer' */
static char *mem4check_pointer( char *return_ptr, int clear )
{
unsigned *large_len_ptr ;
char *malloc_ptr, *test_ptr ;
int i, j ;
large_len_ptr = (unsigned *)(return_ptr - sizeof(unsigned)) ;
malloc_ptr = return_ptr - sizeof(unsigned) - mem4extra_chars ;
for ( j = 0; j < 2; j++ )
{
if (j == 0)
test_ptr = malloc_ptr ;
else
test_ptr = malloc_ptr + *large_len_ptr - mem4extra_chars ;
for ( i = 0 ; i < mem4extra_chars ; i++ )
if ( test_ptr[i] != mem4check_char )
e4severe( e4result, E4_RESULT_CMP ) ;
}
if ( clear == 1 ) /* null the memory to potentially detect re-use, including clearing check chars */
memset( malloc_ptr, 0, *large_len_ptr ) ;
return malloc_ptr ;
}
static void mem4push_pointer( char *ptr )
{
#ifdef S4WINDOWS
HANDLE handle, *h_ptr, *old_h_ptr ;
h_ptr = (HANDLE *)0 ;
#endif
if ( mem4num_pointer < 0 )
{
#ifdef S4WINDOWS
#ifdef __DLL__
handle = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, (DWORD) sizeof(char *) * 100 + sizeof(HANDLE) ) ;
#else
handle = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD) sizeof(char *) * 100 + sizeof(HANDLE) ) ;
#endif
if ( handle == (HANDLE) 0 )
e4severe( e4memory, E4_MEMORY_YPU ) ;
h_ptr = (HANDLE *)GlobalLock( handle ) ;
*h_ptr++ = handle ;
mem4test_pointers = (char **)h_ptr ;
#else
mem4test_pointers = (char **)malloc( sizeof(char *) * 100 ) ;
#endif
mem4num_pointer = 100 ;
}
if ( mem4num_pointer == mem4num_used )
{
mem4num_pointer += 100 ;
if ( mem4num_pointer > 10000 )
e4severe( e4result, E4_MEMORY_YPU ) ;
#ifdef S4WINDOWS
old_h_ptr = (HANDLE *)(mem4test_pointers) ;
old_h_ptr-- ; /* get the actual handle */
#ifdef __DLL__
handle = GlobalReAlloc( *old_h_ptr, (DWORD)sizeof(char *) * mem4num_pointer + sizeof( HANDLE ), GMEM_MOVEABLE ) ;
#else
handle = GlobalReAlloc( *old_h_ptr, (DWORD)sizeof(char *) * mem4num_pointer + sizeof( HANDLE ), GMEM_MOVEABLE ) ;
#endif
if ( handle == (HANDLE) 0 )
e4severe( e4memory, E4_MEMORY_YPU ) ;
h_ptr = (HANDLE *)GlobalLock( handle ) ;
*h_ptr++ = handle ;
mem4test_pointers = (char **)h_ptr ;
#else
mem4test_pointers = (char **)realloc( (void *)mem4test_pointers, sizeof(char *)*mem4num_pointer ) ;
#endif
}
if ( mem4test_pointers == 0 )
e4severe( e4memory, E4_MEMORY_YPU ) ;
mem4test_pointers[mem4num_used++] = ptr ;
}
static void mem4pop_pointer( char *ptr )
{
int i ;
for ( i = mem4num_used - 1 ; i >= 0 ; i-- )
if ( mem4test_pointers[i] == ptr )
{
/* This 'memmove' may create compile warning */
memmove( mem4test_pointers+i, mem4test_pointers+i+1, (size_t) (sizeof(char *) * (mem4num_used-i-1))) ;
mem4num_used-- ;
return ;
}
e4severe( e4result, E4_MEMORY_YPO ) ;
}
void S4FUNCTION mem4check_memory()
{
int i ;
for ( i = 0; i < mem4num_used; i++ )
mem4check_pointer( mem4test_pointers[i], 0 ) ;
}
int S4FUNCTION mem4free_check( int max_left )
{
#ifdef S4MEM_PRINT
int i ;
if ( v4print )
for ( i = 0; i < mem4num_used; i++ )
fprintf( stdprn, "\r\nmem4free_check: %p", mem4test_pointers[i] ) ;
else
for ( i = 0; i < mem4num_used; i++ )
printf( "\r\nmem4free_check: %p", mem4test_pointers[i] ) ;
#endif
if ( mem4num_used > max_left )
e4severe( e4result, E4_RESULT_FRE ) ;
return ( mem4num_used ) ;
}
#endif
void *S4FUNCTION mem4alloc( MEM4 *memory_type )
{
#ifdef S4DEBUG
if ( memory_type == 0 )
e4severe( e4parm, E4_MEM4ALLOC ) ;
#endif
return mem4alloc2( memory_type, 0 ) ;
}
Y4CHUNK *S4FUNCTION mem4alloc_chunk( MEM4 *type_ptr )
{
Y4CHUNK *chunk_ptr ;
int n_allocate, i ;
char *ptr ;
n_allocate = type_ptr->unit_expand ;
if ( l4last( &type_ptr->chunks ) == 0 )
n_allocate = type_ptr->unit_start ;
chunk_ptr = (Y4CHUNK *)u4alloc_free( type_ptr->code_base, sizeof( LINK4 ) + (long)n_allocate*type_ptr->unit_size ) ;
if ( chunk_ptr == 0 )
return 0 ;
ptr = (char *)&chunk_ptr->data ;
for ( i = 0 ; i < n_allocate ; i++ )
l4add( &type_ptr->pieces, (LINK4 *)( ptr + i * type_ptr->unit_size ) ) ;
return chunk_ptr ;
}
static void *mem4alloc_low( MEM4 *memory_type )
{
LINK4 *next_piece ;
Y4CHUNK *new_chunk ;
#ifdef S4DEBUG
char *ptr ;
#endif
#ifdef S4OS2SEM
#ifdef S4OS2
#ifdef __DLL__
ULONG flags ;
#endif
#endif
#endif
if ( memory_type == 0 )
return 0 ;
next_piece = (LINK4 *)l4pop( &memory_type->pieces ) ;
if ( next_piece != 0 )
{
#ifdef S4OS2
#ifdef S4OS2SEM
#ifdef __DLL__
/* get access to the memory */
flags = PAG_WRITE | PAG_READ ;
if ( DosGetSharedMem( next_piece, flags ) != 0 )
return 0 ;
#endif
#endif
#endif
#ifdef S4DEBUG
memory_type->n_used++ ;
ptr = mem4fix_pointer( (char *)next_piece, memory_type->unit_size ) ;
#ifdef S4MEM_PRINT
if ( v4print )
fprintf( stdprn, "\r\n Y4ALLOC: %p", ptr );
else
printf( "\r\n Y4ALLOC: %p", ptr);
#endif
mem4push_pointer( ptr ) ;
return (void *)ptr ;
#else
return next_piece ;
#endif
}
if ( (new_chunk = mem4alloc_chunk( memory_type )) == 0 )
return 0 ;
l4add( &memory_type->chunks, &new_chunk->link ) ;
memory_type->n_used++ ;
#ifdef S4DEBUG
ptr = mem4fix_pointer( (char *)l4pop(&memory_type->pieces),
memory_type->unit_size ) ;
#ifdef S4MEM_PRINT
if ( v4print )
fprintf(stdprn, "\r\n Y4ALLOC: %p", ptr);
else
printf( "\r\n Y4ALLOC: %p", ptr);
#endif
mem4push_pointer( ptr ) ;
return (void *)ptr ;
#else
return l4pop( &memory_type->pieces ) ;
#endif
}
void *S4FUNCTION mem4alloc2( MEM4 *memory_type, CODE4 *c4 )
{
void *ptr ;
if ( c4 )
if ( c4->error_code < 0 )
return 0 ;
#ifdef S4OS2SEM
#ifdef S4OS2
if ( mem4start( memory_type->code_base ) != 0 )
return 0 ;
#endif
#endif
ptr = mem4alloc_low( memory_type ) ;
#ifdef S4OS2SEM
#ifdef S4OS2
mem4stop( memory_type->code_base ) ;
#endif
#endif
if ( ptr == 0 )
{
if ( c4 )
e4set( c4, e4memory ) ;
return 0 ;
}
#ifdef S4DEBUG
memset( ptr, 0, memory_type->unit_size - mem4extra_tot ) ;
#else
memset( ptr, 0, memory_type->unit_size ) ;
#endif
return ptr ;
}
MEM4 *S4FUNCTION mem4create( CODE4 *c4, int start, unsigned unit_size, int expand, int is_temp )
{
MEM4 *on_type ;
#ifdef S4OS2SEM
#ifdef S4OS2
#ifdef __DLL__
ULONG flags ;
#endif
#endif
#endif
#ifdef S4DEBUG
if ( start < 0 || expand < 0 )
e4severe( e4parm, E4_MEM4CREATE ) ;
unit_size += 2 * mem4extra_chars + sizeof( unsigned ) ;
#ifdef S4OS2
if ( c4 == 0 )
e4severe( e4info, "OS/2 mem4create() requires valid CodeBase pointer" ) ;
#endif
#endif
if ( c4 )
if ( c4->error_code < 0 )
return 0 ;
#ifdef S4OS2SEM
#ifdef S4OS2
if ( mem4start( c4 ) != 0 )
return 0 ;
#endif
#endif
if ( !is_temp )
for( on_type = 0 ; ; )
{
on_type = (MEM4 *)l4next( &used, on_type ) ;
if ( on_type == 0 )
break ;
#ifdef S4OS2
#ifdef S4OS2SEM
#ifdef __DLL__
/* get access to the memory */
flags = PAG_WRITE | PAG_READ ;
if ( DosGetSharedMem( on_type, flags ) != 0 )
return 0 ;
#endif
#endif
#endif
if ( on_type->unit_size == unit_size && on_type->n_repeat > 0 )
{
/* Match */
if ( start > on_type->unit_start )
on_type->unit_start = start ;
if ( expand > on_type->unit_expand)
on_type->unit_expand = expand ;
on_type->n_repeat++ ;
#ifdef S4OS2
#ifdef S4OS2SEM
mem4stop( c4 ) ;
#endif
#endif
return on_type ;
}
}
/* Allocate memory for another MEM4 */
on_type = (MEM4 *)l4last( &avail ) ;
if ( on_type == 0 )
{
MEMORY4GROUP *group ;
int i ;
group = (MEMORY4GROUP *)u4alloc_free( c4, sizeof( MEMORY4GROUP ) ) ;
if ( group == 0 )
{
if ( c4 )
e4set( c4, e4memory ) ;
#ifdef S4OS2SEM
#ifdef S4OS2
mem4stop( c4 ) ;
#endif
#endif
return 0 ;
}
for ( i = 0 ; i < mem4num_types ; i++ )
l4add( &avail, group->types + i ) ;
on_type = (MEM4 *)l4last( &avail ) ;
l4add( &groups, group ) ;
}
l4remove( &avail, on_type ) ;
memset( (void *)on_type, 0, sizeof( MEM4 ) ) ;
l4add( &used, on_type ) ;
#ifdef S4OS2SEM
#ifdef S4OS2
mem4stop( c4 ) ;
#endif
#endif
on_type->unit_start = start ;
on_type->unit_size = unit_size ;
on_type->unit_expand= expand ;
on_type->n_repeat = 1 ;
on_type->n_used = 0 ;
if ( is_temp )
on_type->n_repeat = -1 ;
#ifdef S4MEM_PRINT
if ( v4print )
fprintf( stdprn, "\r\n MEM4: %p", on_type ) ;
else
printf( "\r\n MEM4: %p", on_type ) ;
#endif
on_type->code_base = c4 ;
return on_type ;
}
void *S4FUNCTION mem4create_alloc( CODE4 *c4, MEM4 **type_ptr_ptr, int start, unsigned unit_size, int expand, int is_temp)
{
if ( *type_ptr_ptr == 0 )
{
*type_ptr_ptr = mem4create( c4, start, unit_size, expand, is_temp ) ;
if ( *type_ptr_ptr == 0 )
return 0 ;
}
return mem4alloc2( *type_ptr_ptr, c4 ) ;
}
void S4FUNCTION mem4free( MEM4 *memory_type, void *free_ptr )
{
if ( memory_type == 0 || free_ptr == 0 )
return ;
memory_type->n_used-- ;
#ifdef S4DEBUG
if ( memory_type->n_used < 0 )
e4severe( e4result, E4_MEM4FREE ) ;
#ifdef S4MEM_PRINT
if ( v4print )
fprintf(stdprn, "\r\n Y4FREE: %p", free_ptr ) ;
else
printf( "\r\n Y4FREE: %p", free_ptr ) ;
#endif
mem4pop_pointer( (char *)free_ptr ) ;
l4add( &memory_type->pieces, (LINK4 *)mem4check_pointer( (char *)free_ptr, 0 ) ) ;
/* memset( (void *)&free_ptr, 0, sizeof(free_ptr) ) ; */
#else
l4add( &memory_type->pieces, (LINK4 *)free_ptr ) ;
#endif
}
void S4FUNCTION mem4release( MEM4 *memory_type )
{
void *ptr ;
if ( memory_type == 0 )
return ;
memory_type->n_repeat-- ;
if ( memory_type->n_repeat <= 0 )
{
for(;;)
{
ptr = l4pop( &memory_type->chunks) ;
if ( ptr == 0 )
break ;
u4free( ptr ) ;
}
l4remove( &used, memory_type ) ;
l4add( &avail, memory_type ) ;
#ifdef S4MEM_PRINT
if ( v4print )
fprintf( stdprn, "\r\n Y4RELEASE: %p", memory_type ) ;
else
printf( "\r\n Y4RELEASE: %p", memory_type ) ;
#endif
}
}
#ifdef S4OLD_CODE
MEM4 *S4FUNCTION mem4type( int start, unsigned unit_size, int expand, int is_temp)
{
return mem4create( 0, start, unit_size, expand, is_temp ) ;
}
#endif
#ifdef S4MAX
long mem4max_memory = 0x4000 ;
long mem4allocated = 0L ;
#ifndef S4DEBUG
S4DEBUG should be set with S4MAX (force compile error.)
#endif
#endif
void *S4FUNCTION u4alloc( long n )
{
size_t s ;
char *ptr ;
#ifdef S4OS2SEM
#ifdef __DLL__
#ifdef S4OS2
ULONG flags;
APIRET rc;
#endif
#endif
#endif
#ifdef S4DEBUG
if ( n == 0L )
e4severe( e4parm, E4_PARM_ZER ) ;
n += mem4extra_chars*2 + sizeof(unsigned) ;
#endif
#ifdef S4MAX
/* Assumes 'mem4max_memory' is less than the actual maximum */
if ( mem4allocated + n > mem4max_memory )
return 0 ;
mem4allocated += n ;
#endif
s = (size_t) n ;
if ( n > (long) s )
return 0 ;
#ifdef S4WINDOWS
{
HANDLE handle, *h_ptr ;
h_ptr = (HANDLE *)0 ;
#ifdef __DLL__
handle = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, (DWORD) s+ sizeof(HANDLE) ) ;
#else
handle = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD) s+ sizeof(HANDLE) ) ;
#endif
if ( handle == (HANDLE) 0 )
return 0 ;
h_ptr = (HANDLE *)GlobalLock( handle ) ;
*h_ptr++ = handle ;
ptr = (char *)h_ptr ;
}
#else
#ifdef __DLL__
#ifdef S4OS2SEM
#ifndef S4OS2
error invalid switch configuration
#endif
flags = PAG_WRITE | PAG_READ | OBJ_GETTABLE ;
rc = DosAllocSharedMem( (void *)&ptr, 0, s, flags ) ;
if (rc != 0)
return 0 ;
flags = PAG_WRITE | PAG_READ ;
rc = DosGetSharedMem( ptr, flags ) ;
if ( rc != 0 )
return 0 ;
#else
ptr = (char *)malloc( s ) ;
if ( ptr == 0 )
return 0 ;
#ifndef S4PASCAL_WIN
#ifndef S4DEBUG
memset( ptr, 0, s ) ;
#endif
#endif
#endif
#else
ptr = (char *)malloc( s ) ;
if ( ptr == 0 )
return 0 ;
/* Borland malloc of 64K (or close to) will */
#ifdef __TURBOC__ /* result in corruption of segment memory due */
if ( (ptr+s-1 <= ptr) && (s > 1 )) /* to wrap-around problems */
{
free( ptr ) ;
return 0 ;
}
#endif
#ifndef S4PASCAL_WIN
#ifndef S4DEBUG
memset( ptr, 0, s ) ;
#endif
#endif
#endif
#endif
#ifdef S4DEBUG
ptr = mem4fix_pointer( ptr, s ) ;
mem4push_pointer( ptr ) ;
memset( ptr, 0, s-mem4extra_chars*2 - sizeof(unsigned) ) ;
#endif
#ifdef S4MEM_PRINT
if ( v4print )
fprintf( stdprn, "\r\nU4ALLOC: %p # bytes alloc: %ld", ptr, n );
else
printf("\r\nU4ALLOC: %p # bytes alloc: %ld", ptr, n);
#endif
return (void *)ptr ;
}
void *S4FUNCTION u4alloc_er( CODE4 S4PTR *c4, long n )
{
void *ptr = u4alloc_free( c4, n ) ;
if ( ptr == 0 && c4 )
e4( c4, e4memory, 0 ) ;
return ptr ;
}
void S4FUNCTION u4free( void *ptr )
{
#ifdef S4WINDOWS
HANDLE hand ;
#endif
#ifdef S4MAX
unsigned *amount ;
#endif
if ( ptr == 0 )
return ;
#ifdef S4MAX
amount = (unsigned *)ptr ;
mem4allocated -= amount[-1] ;
#endif
#ifdef S4WINDOWS
#ifdef S4DEBUG
mem4pop_pointer( (char *)ptr ) ;
hand = ((HANDLE *)mem4check_pointer( (char *)ptr, 1 ))[-1] ;
#else
hand = ((HANDLE *)ptr)[-1] ;
#endif
GlobalUnlock( hand ) ;
hand = GlobalFree( hand ) ;
if ( hand != (HANDLE) 0 )
e4severe( e4memory, E4_MEMORY_ERR ) ;
#else
#ifdef S4DEBUG
mem4pop_pointer( (char *)ptr ) ;
#ifdef S4MEM_PRINT
if ( v4print )
fprintf( stdprn, "\r\nU4FREE: %p", ptr ) ;
else
printf( "\r\nU4FREE: %p", ptr );
#endif
free(mem4check_pointer( (char *)ptr, 1 ) ) ;
#else
#ifdef S4MEM_PRINT
if ( v4print )
fprintf( stdprn, "\r\nU4FREE: %p", ptr ) ;
else
printf( "\r\nU4FREE: %p", ptr );
#endif
free( ptr ) ;
#endif
#endif
}
void S4FUNCTION mem4reset()
{
MEM4 *on_type ;
LINK4 *on_chunk, *on_group ;
#ifdef S4WINDOWS
HANDLE hand ;
#endif
#ifdef S4LOCK_CHECK
e4severe( e4result, E4_RESULT_S4L ) ;
#endif
for( on_type = 0 ;; )
{
on_type = (MEM4 *)l4next(&used,on_type) ;
if ( on_type == 0 )
break ;
do
{
on_chunk = (LINK4 *)l4pop( &on_type->chunks) ;
u4free( on_chunk ) ; /* free of 0 still succeeds */
} while ( on_chunk ) ;
}
for( ;; )
{
on_group = (LINK4 *)l4pop( &groups ) ;
if ( on_group == 0 )
break ;
u4free( on_group ) ;
}
#ifdef S4DEBUG
if ( mem4num_pointer > 0 )
{
#ifdef S4WINDOWS
hand = ((HANDLE *)mem4test_pointers)[-1] ;
GlobalUnlock( hand ) ;
hand = GlobalFree( hand ) ;
if ( hand != (HANDLE)0 )
e4severe( e4memory, E4_MEMORY_ERR ) ;
#else
#ifdef S4MEM_PRINT
if ( v4print )
fprintf( stdprn, "\r\nMEM4RESET: %p", mem4test_pointers ) ;
else
printf( "\r\nMEM4RESET: %p", mem4test_pointers );
#endif
free( (void *)mem4test_pointers ) ;
#endif
mem4test_pointers = 0 ;
mem4num_pointer = -1 ;
mem4num_used = 0 ;
}
#endif
mem4init() ;
}
void S4FUNCTION mem4init()
{
memset( (void *)&avail, 0, sizeof( avail ) ) ;
memset( (void *)&used, 0, sizeof( used ) ) ;
memset( (void *)&groups, 0, sizeof( groups ) ) ;
}