4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-14 17:59:28 +08:00
newlib-cygwin/winsup/cygwin/malloc_wrapper.cc
Christopher Faylor c433f4617f Throughout, remove "include <errno.h>" from files which already include
cygerrno.h.
* include/cygwin/config.h (__DYNAMIC_REENT__): Define.
* include/cygwin/version.h: Bump API minor version.
* cygwin.din: Export __getreent
* cygerrno.h: Include errno.h.  Fix places where _impure_ptr is used directly
to store the errno value.
* debug.cc (__set_errno): Ditto.
* errno.cc: Remove _RRENT_ONLY define to get errno.cc compiled.
* signal.cc: Rename _reent_clib to _REENT throughout.
* thread.h (reent_clib): Remove prototype.
* thread.cc (reent_clib): Rename reent_clib to __getreent.  Return _impure_ptr
until MTinterface is initialized.
(reent_winsup): Fix a possible SEGV when _r == NULL.  Return NULL instead.
* MTinterface::fixup_after_fork: Switch reent back to _impure_ptr to keep
signal handling running when fork is called from a thread other than the
mainthread.
2003-06-16 03:24:13 +00:00

334 lines
6.1 KiB
C++

/* malloc_wrapper.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
Originally 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>
#include <assert.h>
#include "security.h"
#include "fhandler.h"
#include "path.h"
#include "dtable.h"
#include "cygerrno.h"
#include "cygheap.h"
#include "heap.h"
#include "sync.h"
#include "perprocess.h"
#include "cygmalloc.h"
#include <malloc.h>
extern "C" struct mallinfo dlmallinfo ();
/* 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;
static int use_internal_malloc = 1;
#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;
assert (!incygheap (p));
assert (inheap (p));
free (p);
}
#undef free
extern "C" void *
_realloc_r (struct _reent *, void *p, size_t size)
{
export_malloc_called = 1;
assert (!incygheap (p));
assert (inheap (p));
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
#endif
/* These routines are used by the application if it
doesn't provide its own malloc. */
extern "C" void
free (void *p)
{
malloc_printf ("(%p), called by %p", p, __builtin_return_address (0));
if (!use_internal_malloc)
user_data->free (p);
else
{
__malloc_lock ();
dlfree (p);
__malloc_unlock ();
}
}
extern "C" void *
malloc (size_t size)
{
void *res;
export_malloc_called = 1;
if (!use_internal_malloc)
res = user_data->malloc (size);
else
{
__malloc_lock ();
res = dlmalloc (size);
__malloc_unlock ();
}
malloc_printf ("(%d) = %x, called by %p", size, res, __builtin_return_address (0));
return res;
}
extern "C" void *
realloc (void *p, size_t size)
{
void *res;
if (!use_internal_malloc)
res = user_data->realloc (p, size);
else
{
__malloc_lock ();
res = dlrealloc (p, size);
__malloc_unlock ();
}
malloc_printf ("(%x, %d) = %x, called by %x", p, size, res, __builtin_return_address (0));
return res;
}
extern "C" void *
calloc (size_t nmemb, size_t size)
{
void *res;
if (!use_internal_malloc)
res = user_data->calloc (nmemb, size);
else
{
__malloc_lock ();
res = dlcalloc (nmemb, size);
__malloc_unlock ();
}
malloc_printf ("(%d, %d) = %x, called by %x", nmemb, size, res, __builtin_return_address (0));
return res;
}
extern "C" void *
memalign (size_t alignment, size_t bytes)
{
void *res;
if (!use_internal_malloc)
{
set_errno (ENOSYS);
res = NULL;
}
else
{
__malloc_lock ();
res = dlmemalign (alignment, bytes);
__malloc_unlock ();
}
return res;
}
extern "C" void *
valloc (size_t bytes)
{
void *res;
if (!use_internal_malloc)
{
set_errno (ENOSYS);
res = NULL;
}
else
{
__malloc_lock ();
res = dlvalloc (bytes);
__malloc_unlock ();
}
return res;
}
extern "C" size_t
malloc_usable_size (void *p)
{
size_t res;
if (!use_internal_malloc)
{
set_errno (ENOSYS);
res = 0;
}
else
{
__malloc_lock ();
res = dlmalloc_usable_size (p);
__malloc_unlock ();
}
return res;
}
extern "C" int
malloc_trim (size_t pad)
{
size_t res;
if (!use_internal_malloc)
{
set_errno (ENOSYS);
res = 0;
}
else
{
__malloc_lock ();
res = dlmalloc_trim (pad);
__malloc_unlock ();
}
return res;
}
extern "C" int
mallopt (int p, int v)
{
int res;
if (!use_internal_malloc)
{
set_errno (ENOSYS);
res = 0;
}
else
{
__malloc_lock ();
res = dlmallopt (p, v);
__malloc_unlock ();
}
return res;
}
extern "C" void
malloc_stats ()
{
if (!use_internal_malloc)
set_errno (ENOSYS);
else
{
__malloc_lock ();
dlmalloc_stats ();
__malloc_unlock ();
}
return;
}
extern "C" struct mallinfo
mallinfo ()
{
struct mallinfo m;
if (!use_internal_malloc)
set_errno (ENOSYS);
else
{
__malloc_lock ();
m = dlmallinfo ();
__malloc_unlock ();
}
return m;
}
extern "C" char *
strdup (const char *s)
{
char *p;
size_t len = strlen (s) + 1;
if ((p = (char *) malloc (len)) != NULL)
memcpy (p, s, len);
return p;
}
/* 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. */
NO_COPY muto *mallock = NULL;
void
malloc_init ()
{
new_muto (mallock);
/* Check if mallock is provided by application. If so, redirect all
calls to 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
user_data->free (user_data->malloc (16));
#endif
if (!export_malloc_called)
use_internal_malloc = 0;
}
}