3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
15 #include "perprocess.h"
16 #include "miscfuncs.h"
17 #include "cygmalloc.h"
19 extern "C" struct mallinfo
dlmallinfo ();
21 /* we provide these stubs to call into a user's
22 provided malloc if there is one - otherwise
23 functions we provide - like strdup will cause
24 problems if malloced on our heap and free'd on theirs.
27 static bool use_internal
= true;
28 static bool internal_malloc_determined
;
30 /* Helper function to generate the correct caller address. For external
31 calls, the return address on the stack is _sigbe. In that case the
32 actual caller return address is on the cygtls stack. Use this function
33 via the macro caller_return_address. */
34 extern "C" void _sigbe ();
37 __caller_return_address (void *builtin_ret_addr
)
39 return builtin_ret_addr
== &_sigbe
40 ? (void *) _my_tls
.retaddr () : builtin_ret_addr
;
43 #define caller_return_address() \
44 __caller_return_address (__builtin_return_address (0))
45 void * __caller_return_address (void *);
47 /* Return an address from the import jmp table of main program. */
49 import_address (void *imp
)
53 if (*((uint16_t *) imp
) == 0x25ff)
55 const char *ptr
= (const char *) imp
;
56 const uintptr_t *jmpto
= (uintptr_t *)
57 (ptr
+ 6 + *(int32_t *)(ptr
+ 2));
58 return (void *) *jmpto
;
61 __except (NO_ERROR
) {}
66 /* These routines are used by the application if it
67 doesn't provide its own malloc. */
72 malloc_printf ("(%p), called by %p", p
, caller_return_address ());
88 res
= user_data
->malloc (size
);
92 res
= dlmalloc (size
);
95 malloc_printf ("(%ld) = %p, called by %p", size
, res
,
96 caller_return_address ());
101 realloc (void *p
, size_t size
)
105 res
= user_data
->realloc (p
, size
);
109 res
= dlrealloc (p
, size
);
112 malloc_printf ("(%p, %ld) = %p, called by %p", p
, size
, res
,
113 caller_return_address ());
117 /* BSD extension: Same as realloc, just if it fails to allocate new memory,
118 it frees the incoming pointer. */
120 reallocf (void *p
, size_t size
)
122 void *res
= realloc (p
, size
);
129 calloc (size_t nmemb
, size_t size
)
133 res
= user_data
->calloc (nmemb
, size
);
137 res
= dlcalloc (nmemb
, size
);
140 malloc_printf ("(%ld, %ld) = %p, called by %p", nmemb
, size
, res
,
141 caller_return_address ());
146 posix_memalign (void **memptr
, size_t alignment
, size_t bytes
)
152 return user_data
->posix_memalign (memptr
, alignment
, bytes
);
153 if ((alignment
& (alignment
- 1)) != 0)
156 res
= dlmemalign (alignment
, bytes
);
165 memalign (size_t alignment
, size_t bytes
)
176 res
= dlmemalign (alignment
, bytes
);
184 valloc (size_t bytes
)
195 res
= dlvalloc (bytes
);
203 malloc_usable_size (void *p
)
214 res
= dlmalloc_usable_size (p
);
222 malloc_trim (size_t pad
)
233 res
= dlmalloc_trim (pad
);
241 mallopt (int p
, int v
)
252 res
= dlmallopt (p
, v
);
272 extern "C" struct mallinfo
278 memset (&m
, 0, sizeof m
);
292 strdup (const char *s
)
295 size_t len
= strlen (s
) + 1;
296 if ((p
= (char *) malloc (len
)) != NULL
)
301 /* We use a SRW lock to lock access to the malloc data structures. This
302 permits malloc to be called from different threads. Note that it does
303 not make malloc reentrant, and it does not permit a signal handler to
304 call malloc. The malloc code in newlib will call __malloc_lock and
305 __malloc_unlock at appropriate times. */
307 SRWLOCK NO_COPY mallock
= SRWLOCK_INIT
;
312 /* Check if malloc is provided by application. If so, redirect all
313 calls to malloc/free/realloc to application provided. This may
314 happen if some other dll calls cygwin's malloc, but main code provides
316 if (!internal_malloc_determined
)
318 extern void *_sigfe_malloc
;
319 /* Decide if we are using our own version of malloc by testing the import
320 address from user_data. */
321 use_internal
= user_data
->malloc
== malloc
322 || import_address ((void *) user_data
->malloc
)
324 malloc_printf ("using %s malloc", use_internal
? "internal" : "external");
325 internal_malloc_determined
= true;