summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/malloc_wrapper.cc
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2000-02-17 19:38:33 +0000
committerChristopher Faylor <me@cgf.cx>2000-02-17 19:38:33 +0000
commit1fd5e000ace55b323124c7e556a7a864b972a5c4 (patch)
treedc4fcf1e5e22a040716ef92c496b8d94959b2baa /winsup/cygwin/malloc_wrapper.cc
parent369d8a8fd5e887eca547bf34bccfdf755c9e5397 (diff)
downloadcygnal-1fd5e000ace55b323124c7e556a7a864b972a5c4.tar.gz
cygnal-1fd5e000ace55b323124c7e556a7a864b972a5c4.tar.bz2
cygnal-1fd5e000ace55b323124c7e556a7a864b972a5c4.zip
import winsup-2000-02-17 snapshot
Diffstat (limited to 'winsup/cygwin/malloc_wrapper.cc')
-rw-r--r--winsup/cygwin/malloc_wrapper.cc221
1 files changed, 221 insertions, 0 deletions
diff --git a/winsup/cygwin/malloc_wrapper.cc b/winsup/cygwin/malloc_wrapper.cc
new file mode 100644
index 000000000..aa4891b8e
--- /dev/null
+++ b/winsup/cygwin/malloc_wrapper.cc
@@ -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");
+}