import winsup-2000-02-17 snapshot
This commit is contained in:
221
winsup/cygwin/malloc_wrapper.cc
Normal file
221
winsup/cygwin/malloc_wrapper.cc
Normal file
@@ -0,0 +1,221 @@
|
||||
/* malloc.cc for WIN32.
|
||||
|
||||
Copyright 1996, 1997, 1998 Cygnus Solutions.
|
||||
|
||||
Written by Steve Chamberlain of Cygnus Support
|
||||
sac@cygnus.com
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
This software is a copyrighted work licensed under the terms of the
|
||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include "winsup.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* we provide these stubs to call into a user's
|
||||
provided malloc if there is one - otherwise
|
||||
functions we provide - like strdup will cause
|
||||
problems if malloced on our heap and free'd on theirs.
|
||||
*/
|
||||
|
||||
static int export_malloc_called = 0;
|
||||
static int use_internal_malloc = 1;
|
||||
|
||||
#undef in
|
||||
#undef out
|
||||
#define in(x)
|
||||
#define out(x)
|
||||
|
||||
#ifdef MALLOC_DEBUG
|
||||
extern "C" void * _sbrk (size_t incr_arg);
|
||||
|
||||
#if 0
|
||||
extern "C" void *
|
||||
_sbrk_r (struct _reent *, size_t incr_arg)
|
||||
{
|
||||
return _sbrk (incr_arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" void *
|
||||
_malloc_r (struct _reent *, size_t size)
|
||||
{
|
||||
export_malloc_called = 1;
|
||||
return malloc (size);
|
||||
}
|
||||
#undef malloc
|
||||
|
||||
extern "C" void *
|
||||
_calloc_r (struct _reent *, size_t nmemb, size_t size)
|
||||
{
|
||||
export_malloc_called = 1;
|
||||
return calloc (nmemb, size);
|
||||
}
|
||||
#undef calloc
|
||||
|
||||
extern "C" void
|
||||
_free_r (struct _reent *, void *p)
|
||||
{
|
||||
export_malloc_called = 1;
|
||||
free (p);
|
||||
}
|
||||
#undef free
|
||||
|
||||
extern "C" void *
|
||||
_realloc_r (struct _reent *, void *p, size_t size)
|
||||
{
|
||||
export_malloc_called = 1;
|
||||
return realloc (p, size);
|
||||
}
|
||||
#undef realloc
|
||||
|
||||
extern "C" char *
|
||||
strdup_dbg (const char *s, const char *file, int line)
|
||||
{
|
||||
char *p;
|
||||
export_malloc_called = 1;
|
||||
if ((p = (char *) malloc_dbg (strlen (s) + 1, file, line)) != NULL)
|
||||
strcpy (p, s);
|
||||
return p;
|
||||
}
|
||||
|
||||
#undef strdup
|
||||
extern "C" char *
|
||||
strdup (const char *s)
|
||||
{
|
||||
return strdup_dbg (s, __FILE__, __LINE__);
|
||||
}
|
||||
#else
|
||||
/* Call though the application pointer,
|
||||
which either points to export_malloc, or the application's
|
||||
own version. */
|
||||
|
||||
void *
|
||||
malloc (size_t size)
|
||||
{
|
||||
void *res;
|
||||
res = user_data->malloc (size);
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
free (void *p)
|
||||
{
|
||||
user_data->free (p);
|
||||
}
|
||||
|
||||
void *
|
||||
realloc (void *p, size_t size)
|
||||
{
|
||||
void *res;
|
||||
res = user_data->realloc (p, size);
|
||||
return res;
|
||||
}
|
||||
|
||||
void *
|
||||
calloc (size_t nmemb, size_t size)
|
||||
{
|
||||
void *res;
|
||||
res = user_data->calloc (nmemb, size);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* These routines are used by the application if it
|
||||
doesn't provide its own malloc. */
|
||||
|
||||
extern "C"
|
||||
void
|
||||
export_free (void *p)
|
||||
{
|
||||
malloc_printf ("(%p), called by %x", p, ((int *)&p)[-1]);
|
||||
if (use_internal_malloc)
|
||||
_free_r (_impure_ptr, p);
|
||||
else
|
||||
user_data->free (p);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void *
|
||||
export_malloc (int size)
|
||||
{
|
||||
void *res;
|
||||
export_malloc_called = 1;
|
||||
if (use_internal_malloc)
|
||||
res = _malloc_r (_impure_ptr, size);
|
||||
else
|
||||
res = user_data->malloc (size);
|
||||
malloc_printf ("(%d) = %x, called by %x", size, res, ((int *)&size)[-1]);
|
||||
return res;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void *
|
||||
export_realloc (void *p, int size)
|
||||
{
|
||||
void *res;
|
||||
if (use_internal_malloc)
|
||||
res = _realloc_r (_impure_ptr, p, size);
|
||||
else
|
||||
res = user_data->realloc (p, size);
|
||||
malloc_printf ("(%x, %d) = %x, called by %x", p, size, res, ((int *)&p)[-1]);
|
||||
return res;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void *
|
||||
export_calloc (size_t nmemb, size_t size)
|
||||
{
|
||||
void *res;
|
||||
if (use_internal_malloc)
|
||||
res = _calloc_r (_impure_ptr, nmemb, size);
|
||||
else
|
||||
res = user_data->calloc (nmemb, size);
|
||||
malloc_printf ("(%d, %d) = %x, called by %x", nmemb, size, res, ((int *)&nmemb)[-1]);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* We use a critical section to lock access to the malloc data
|
||||
structures. This permits malloc to be called from different
|
||||
threads. Note that it does not make malloc reentrant, and it does
|
||||
not permit a signal handler to call malloc. The malloc code in
|
||||
newlib will call __malloc_lock and __malloc_unlock at appropriate
|
||||
times. */
|
||||
|
||||
static NO_COPY CRITICAL_SECTION malloc_critical_section;
|
||||
|
||||
void
|
||||
malloc_init ()
|
||||
{
|
||||
InitializeCriticalSection (&malloc_critical_section);
|
||||
/* Check if mallock is provided by application. If so, redirect all
|
||||
calls to export_malloc/free/realloc to application provided. This may
|
||||
happen if some other dll calls cygwin's malloc, but main code provides
|
||||
its own malloc */
|
||||
if (!user_data->forkee)
|
||||
{
|
||||
#ifdef MALLOC_DEBUG
|
||||
_free_r (NULL, _malloc_r (NULL, 16));
|
||||
#else
|
||||
free (malloc (16));
|
||||
#endif
|
||||
if (!export_malloc_called)
|
||||
use_internal_malloc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void
|
||||
__malloc_lock (struct _reent *ptr)
|
||||
{
|
||||
SetResourceLock(LOCK_MEMORY_LIST,WRITE_LOCK|READ_LOCK," __malloc_lock");
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void
|
||||
__malloc_unlock (struct _reent *ptr)
|
||||
{
|
||||
ReleaseResourceLock(LOCK_MEMORY_LIST,WRITE_LOCK|READ_LOCK," __malloc_unlock");
|
||||
}
|
Reference in New Issue
Block a user