Files
cdesktop/cde/programs/dtksh/ksh93/src/lib/libast/vmalloc/malloc.c
2019-08-20 12:52:43 +02:00

484 lines
10 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $XConsortium: malloc.c /main/2 1996/05/08 20:00:43 drk $ */
/***************************************************************
* *
* AT&T - PROPRIETARY *
* *
* THIS IS PROPRIETARY SOURCE CODE LICENSED BY *
* AT&T CORP. *
* *
* Copyright (c) 1995 AT&T Corp. *
* All Rights Reserved *
* *
* This software is licensed by AT&T Corp. *
* under the terms and conditions of the license in *
* http://www.research.att.com/orgs/ssr/book/reuse *
* *
* This software was created by the *
* Software Engineering Research Department *
* AT&T Bell Laboratories *
* *
* For further information contact *
* gsf@research.att.com *
* *
***************************************************************/
#include <ast_lib.h>
#if _std_malloc || _INSTRUMENT_ || cray
int _STUB_malloc;
#else
#include "vmhdr.h"
/* malloc compatibility functions.
** These are aware of debugging/profiling and driven by the environment variables:
** VMETHOD: select an allocation method by name.
** VMPROFILE: if is a file name, profile memory usage and write output to it.
** VMDEBUG:
** a: abort on any warning
** #: period to check arena.
** 0x#: address to watch.
** VMTRACE: if is a file name, turn on tracing and output
** trace data to the given file.
**
** Written by (Kiem-)Phong Vo, kpv@research.att.com, 01/16/94.
*/
#if !_PACKAGE_ast
_BEGIN_EXTERNS_
extern int atexit _ARG_(( void(*)() ));
extern char* getenv _ARG_(( const char* ));
extern int creat _ARG_(( const char*, int ));
extern int close _ARG_(( int ));
extern int getpid _ARG_(( void ));
_END_EXTERNS_
#endif
#ifdef malloc
#undef malloc
#endif
#ifdef free
#undef free
#endif
#ifdef realloc
#undef realloc
#endif
#ifdef calloc
#undef calloc
#endif
#ifdef cfree
#undef cfree
#endif
#ifdef memalign
#undef memalign
#endif
#ifdef valloc
#undef valloc
#endif
#if __STD_C
static ulong atou(char** sp)
#else
static ulong atou(sp)
char** sp;
#endif
{
char* s = *sp;
ulong v = 0;
if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X') )
{ for(s += 2; *s; ++s)
{ if(*s >= '0' && *s <= '9')
v = (v << 4) + (*s - '0');
else if(*s >= 'a' && *s <= 'f')
v = (v << 4) + (*s - 'a') + 10;
else if(*s >= 'A' && *s <= 'F')
v = (v << 4) + (*s - 'A') + 10;
else break;
}
}
else
{ for(; *s; ++s)
{ if(*s >= '0' && *s <= '9')
v = v*10 + (*s - '0');
else break;
}
}
*sp = s;
return v;
}
static int _Vmflinit = 0;
static ulong _Vmdbcheck = 0;
static ulong _Vmdbtime = 0;
static int _Vmpffd = -1;
#define VMFLINIT() \
{ if(!_Vmflinit) vmflinit(); \
if(_Vmdbcheck && (_Vmdbtime++ % _Vmdbcheck) == 0 && \
Vmregion->meth.meth == VM_MTDEBUG) \
vmdbcheck(Vmregion); \
}
#if __STD_C
static char* insertpid(char* begs, char* ends)
#else
static char* insertpid(begs,ends)
char* begs;
char* ends;
#endif
{ int pid;
char* s;
if((pid = getpid()) < 0)
return NIL(char*);
s = ends;
do
{ if(s == begs)
return NIL(char*);
*--s = '0' + pid%10;
} while((pid /= 10) > 0);
while(s < ends)
*begs++ = *s++;
return begs;
}
#if __STD_C
static int createfile(char* file)
#else
static createfile(file)
char* file;
#endif
{
char buf[1024];
char *next, *endb;
next = buf;
endb = buf + sizeof(buf);
while(*file)
{ if(*file == '%')
{ switch(file[1])
{
case 'p' :
if(!(next = insertpid(next,endb)) )
return -1;
file += 2;
break;
default :
goto copy;
}
}
else
{ copy:
*next++ = *file++;
}
if(next >= endb)
return -1;
}
*next = '\0';
return creat(buf,0644);
}
static void pfprint()
{
if(Vmregion->meth.meth == VM_MTPROFILE)
vmprofile(Vmregion,_Vmpffd);
}
static int vmflinit()
{
char* env;
Vmalloc_t* vm;
int fd;
ulong addr;
/* this must be done now to avoid any inadvertent recursion (more below) */
_Vmflinit = 1;
/* if getenv() calls malloc(), this may not be caught by the eventual region */
vm = NIL(Vmalloc_t*);
if((env = getenv("VMETHOD")) )
{ if(strcmp(env,"Vmdebug") == 0 || strcmp(env,"vmdebug") == 0)
vm = vmopen(Vmdcsbrk,Vmdebug,0);
else if(strcmp(env,"Vmprofile") == 0 || strcmp(env,"vmprofile") == 0 )
vm = vmopen(Vmdcsbrk,Vmprofile,0);
else if(strcmp(env,"Vmlast") == 0 || strcmp(env,"vmlast") == 0 )
vm = vmopen(Vmdcsbrk,Vmlast,0);
else if(strcmp(env,"Vmpool") == 0 || strcmp(env,"vmpool") == 0 )
vm = vmopen(Vmdcsbrk,Vmpool,0);
else if(strcmp(env,"Vmbest") == 0 || strcmp(env,"vmbest") == 0 )
vm = Vmheap;
}
if((!vm || vm->meth.meth == VM_MTDEBUG) &&
(env = getenv("VMDEBUG")) && env[0] )
{ if(vm || (vm = vmopen(Vmdcsbrk,Vmdebug,0)) )
{ reg int setcheck = 0;
while(*env)
{ if(*env == 'a')
vmset(vm,VM_DBABORT,1);
if(*env < '0' || *env > '9')
env += 1;
else if(env[0] == '0' &&
(env[1] == 'x' || env[1] == 'X') )
{ if((addr = atou(&env)) != 0)
vmdbwatch((Void_t*)addr);
}
else
{ _Vmdbcheck = atou(&env);
setcheck = 1;
}
}
if(!setcheck)
_Vmdbcheck = 1;
}
}
if((!vm || vm->meth.meth == VM_MTPROFILE) &&
(env = getenv("VMPROFILE")) && env[0] )
{ _Vmpffd = createfile(env);
if(!vm)
vm = vmopen(Vmdcsbrk,Vmprofile,0);
}
/* slip in the new region now so that malloc() will work fine */
if(vm)
Vmregion = vm;
/* turn on tracing if requested */
if((env = getenv("VMTRACE")) && env[0] && (fd = createfile(env)) >= 0)
{ vmset(Vmregion,VM_TRACE,1);
vmtrace(fd);
}
/* make sure that profile data is output upon exiting */
if(vm && vm->meth.meth == VM_MTPROFILE)
{ if(_Vmpffd < 0)
_Vmpffd = 2;
/* this may wind up calling malloc(), but region is ok now */
atexit(pfprint);
}
else if(_Vmpffd >= 0)
{ close(_Vmpffd);
_Vmpffd = -1;
}
return 0;
}
#if __STD_C
Void_t* malloc(reg size_t size)
#else
Void_t* malloc(size)
reg size_t size;
#endif
{
VMFLINIT();
return (*Vmregion->meth.allocf)(Vmregion,size);
}
#if __STD_C
Void_t* realloc(reg Void_t* data, reg size_t size)
#else
Void_t* realloc(data,size)
reg Void_t* data; /* block to be reallocated */
reg size_t size; /* new size */
#endif
{
VMFLINIT();
return (*Vmregion->meth.resizef)(Vmregion,data,size,VM_RSCOPY|VM_RSFREE);
}
#if __STD_C
void free(reg Void_t* data)
#else
void free(data)
reg Void_t* data;
#endif
{
VMFLINIT();
(void)(*Vmregion->meth.freef)(Vmregion,data);
}
#if __STD_C
Void_t* calloc(reg size_t n_obj, reg size_t s_obj)
#else
Void_t* calloc(n_obj, s_obj)
reg size_t n_obj;
reg size_t s_obj;
#endif
{
reg int* di;
reg char* dc;
reg Void_t* data;
VMFLINIT();
if(!(data = (*Vmregion->meth.allocf)(Vmregion,n_obj*s_obj)) )
return NIL(Void_t*);
n_obj *= s_obj;
s_obj = n_obj/sizeof(int);
n_obj -= s_obj*sizeof(int);
for(di = (int*)data; s_obj > 0; --s_obj )
*di++ = 0;
for(dc = (char*)di; n_obj > 0; --n_obj )
*dc++ = 0;
return data;
}
#if __STD_C
void cfree(reg Void_t* data)
#else
void cfree(data)
reg Void_t* data;
#endif
{
VMFLINIT();
(void)(*Vmregion->meth.freef)(Vmregion,data);
}
#if __STD_C
Void_t* memalign(reg size_t align, reg size_t size)
#else
Void_t* memalign(align, size)
reg size_t align;
reg size_t size;
#endif
{
VMFLINIT();
return (*Vmregion->meth.alignf)(Vmregion,size,align);
}
#if __STD_C
Void_t* valloc(reg size_t size)
#else
Void_t* valloc(size)
reg size_t size;
#endif
{
VMFLINIT();
GETPAGESIZE(_Vmpagesize);
return (*Vmregion->meth.alignf)(Vmregion,size,_Vmpagesize);
}
/* the below collection of functions are aware of files and line numbers */
#define VMSETFL(f,l) (_Vmfile = (f), _Vmline = (l))
#if __STD_C
Void_t* _vmflmalloc(size_t size, char* file, int line)
#else
Void_t* _vmflmalloc(size, file, line)
size_t size;
char* file;
int line;
#endif
{
VMFLINIT();
VMSETFL(file,line);
return malloc(size);
}
#if __STD_C
Void_t* _vmflrealloc(Void_t* data, size_t size, char* file, int line)
#else
Void_t* _vmflrealloc(data,size,file,line)
Void_t* data;
size_t size;
char* file;
int line;
#endif
{
VMFLINIT();
VMSETFL(file,line);
return realloc(data,size);
}
#if __STD_C
void _vmflfree(Void_t* data, char* file, int line)
#else
void _vmflfree(data,file,line)
Void_t* data;
char* file;
int line;
#endif
{
VMFLINIT();
VMSETFL(file,line);
free(data);
}
#if __STD_C
Void_t* _vmflcalloc(size_t n_obj, size_t s_obj, char* file, int line)
#else
Void_t* _vmflcalloc(n_obj, s_obj, file, line)
size_t n_obj;
size_t s_obj;
char* file;
int line;
#endif
{
VMFLINIT();
VMSETFL(file,line);
return calloc(n_obj, s_obj);
}
#if __STD_C
Void_t* _vmflmemalign(size_t align, size_t size, char* file, int line)
#else
Void_t* _vmflmemalign(align, size, file, line)
size_t align;
size_t size;
char* file;
int line;
#endif
{
VMFLINIT();
VMSETFL(file,line);
return memalign(size,align);
}
#if __STD_C
Void_t* _vmflvalloc(size_t size, char* file, int line)
#else
Void_t* _vmflvalloc(size, file, line)
size_t size;
char* file;
int line;
#endif
{
VMFLINIT();
VMSETFL(file,line);
return valloc(size);
}
#endif