4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-29 02:20:21 +08:00
newlib-cygwin/winsup/cygwin/malloc_wrapper.cc
Christopher Faylor 2d1d1eb1e4 * cygtls.h (_threadinfo::call): Remove regparm declaration to work around
compiler bug.
* autoload.cc (TryEnterCriticalSection): Remove.
* dcrt0.cc (dll_crt0_0): Delete inappropriate setting of _my_tls.stackptr to
NULL since it has really bad consequences.  Make 'si' an automatic variable.
* cygtls.cc (_threadinfo::init_thread): Correct thinko which caused thread list
to be allocated every time.
* cygtls.h (CYGTLS_PADSIZE): Define as const int.
* sync.h: Make multiple inclusion safe.
(muto::next): Eliminate.
(muto::exiting_thread): New variable.
(muto::set_exiting_thread): New function.
(new_muto): Change to use different section for mutos since c++ give
inexplicable warning in some cases otherwise.
(new_muto1): Ditto.
* dcrt0.cc (do_exit): Call muto::set_exiting_thread here.
* sync.cc (muto_start): Eliminate.
(muto::acquire): Always give exiting thread a lock.  Never give thread a lock
if exiting.
(muto::release): Ditto for releasing.
* dtable.cc (dtable::init_lock): Unline function and define here.
* dtable.h (lock_cs): Define as a muto since critical sections seem to work
oddly on Windows Me.
(lock): Accommodate switch to muto.
(unlock): Ditto.
* exceptions.cc (setup_handler): Don't worry about acquiring mutos since that
hasn't mattered for a long time.
(signal_exit): Ditto: muto stuff will be handled automatically on exit now.
* Makefile.in (DLL_IMPORTS): Link advapi32 to ensure proper DLL initialization.
* autoload.cc (RegCloseKey): Arbitrarily choose this function as a "seed" to
pull the advapi32 link library in.  So, comment out the autoloading.
* cygtls.cc (_threadinfo::init_thread): Just clear CYGTLS_PADSIZE.
(_threadinfo::remove): Add debugging.
(_threadinfo::find_tls): Ditto.
* cygtls.h (_threadinfo::padding): Make zero length (for now?).
* dcrt0.cc (dll_crt0_0): Move more initialization here from dll_crt0_1.
(dll_crt0_1): See above.
* dtable.h (dtable::lock): Remove commented out critical section locking.
* dtable.h (dtable::init_lock): Remove commented out critical section locking.
* dtable.h (dtable::unlock): Remove commented out critical section locking.
* exceptions.cc (interruptible): bool'ize.
* init.cc (threadfunc_fe): Revert to storing threadfunc at stack bottom.
(munge_threadfunc): Ditto.  Avoid adding overhead to calibration_thread.
(prime_threads): Don't initialize tls stuff.
(dll_entry): Make minor change to initialization order.
* tlsoffsets.h: Regenerate.
* sigproc.cc (wait_sig): Add sanity check for end of process thread exit.
* select.h: Make minor formatting change.
* Makefile.in: Add still more -fomit-frame-pointer functions.
* dtable.h (dtable::lock): New function.
(dtable::unlock): New function.
(dtable::init_lock): New function.
* cygheap.h (HEAP_TLS): Declare new enum value.
(init_cygheap::threadlist): Declare new array.
(init_cygheap::sthreads): Declare new variable.
(cygheap_fdmanip::~cygheap_fdmanip): Use new dtable lock/unlock functions.
(cygheap_fdnew::cygheap_fdnew): Ditto.
(cygheap_fdget::cygheap_fdget): Ditto.
* dtable.cc (dtable_init): Initialize fdtab critical section.
(dtable::fixup_after_fork): Ditto.
(dtable::fixup_after_exec): Ditto.
(dtable::dup2): Use lock/unlock calls to protect access to fdtab.
(dtable::find_fifo): Ditto.
(dtable::fixup_before_fork): Ditto.
(dtable::fixup_before_exec): Ditto.
(dtable::set_file_pointers_for_exec): Ditto.
(dtable::vfork_child_dup): Ditto.
(dtable::vfork_parent_restore): Ditto.
* syscalls.cc (close_all_files): Ditto.
* sync.h (muto::acquired): Declare new function.
(new_muto1): Declare new macro used to specify name of muto storage.
* sync.cc (muto::acquired): Define new function.
* cygthread.cc (cygthread::stub): Remove signal chain removal call since it is
handled during initialization now.
* cygthread.cc (cygthread::simplestub): Remove signal chain removal call since
it is handled during initialization now.
* cygtls.cc (sentry): New class used for locking.  Use throughout.
(_threadinfo::reset_exception): Don't pop stack.
(_threadinfo::find_tls): Move from exceptions.cc.
(_threadinfo::init_thread): Initialize array of threads rather than linked
list.  Take second argument indicating thread function for this thread.
(_threadinfo::remove): Search thread array rather than linked list.  Use sentry
to lock.  Only unlock if we got the lock.
(_threadinfo::find_tls): Ditto for first two.
(handle_threadlist_exception): Handle exceptions when manipulating the thread
list in case of premature thread termination.
(_threadinfo::init_threadlist_exceptions): Ditto.
* cygtls.h (TLS_STACK_SIZE): Decrease size.
(_threadinfo::padding): Add element to avoid overwriting lower part of stack.
(_threadinfo::remove): Add a "wait" argument to control how long we wait for a
lock before removing.
* exceptions.cc (init_exception_handler): Make global.  Take argument to
control exception handler being set.
(ctrl_c_handler): Wait forever when removing self from signal chain.
(_threadinfo::find_tls): Move to cygtls.cc.
(sig_handle): Reorganize detection for thread-specific signals.
* heap.cc (heap_init): Rework slightly.  Make fatal error more verbose.  Remove
malloc initialization since it can't happen during dll attach.
* init.cc (search_for): Move address to search for on stack here.
(threadfunc_ix): Ditto for stack offset.  Make shared so that stack walk
potentially only has to be done once when cygwin processes are running.
(threadfunc_fe): Use standard tls to store thread function (may change back
later).
(calibration_thread): New function.  Potentially called to find threadfunc_ix.
(munge_threadfunc): Search for "search_for" value on stack.  Output warning
when thread func not found on stack.  Use standard tls to store thread
function.
(prime_threads): New function.  Called to prime thread front end.
(dll_entry): Call dll_crt0_0 here when DLL_PROCESS_ATTACH.  Call prime_threads
here.  Try to remove thread from signal list here.
* sigproc.cc (wait_sig): Initialize threadlist exception stuff here.
* thread.cc (pthread::exit): Pass argument to signal list remove function.
* thread.h: Remove obsolete *ResourceLock defines.
* tlsoffsets.h: Regenerate.
* winsup.h (spf): Define temporary debug macro to be deleted later.
* dcrt0.cc (dll_crt0_0): New function, called during DLL initialization.
Mainly consists of code pulled from dll_crt0_1.
(dll_crt0_1): See above.
(_dll_crt0): Wait for initial calibration thread to complete, if appropriate.
Move some stuff to dll_crt0_0.
(initialize_main_tls): Accommodate argument change to
_thread_info::init_thread.
* fork.cc (fork_child): Ditto.
(sync_with_child): Fix debug message.
* external.cc (cygwin_internal): Remove special considerations for
uninitialized dll since initialization happens during dll attach now.
* dlfcn.cc (dlopen): Remove obsolete *ResourceLock calls.
(dlclose): Ditto.
* cygheap.h (init_cygheap::close_ctty): Declare new function.
* cygheap.cc (init_cygheap::close_ctty): Define new function.
* syscalls.cc (close_all_files): Use close_ctty.
(setsid): Ditto.
* cygthread.cc (cygthread::stub): Remove exception initialization.
* cygthread.cc (cygthread::stub): Remove exception initialization.
(cygthread::simplestub): Ditto.
* thread.cc (pthread::thread_init_wrapper): Ditto.
* cygtls.cc (_last_thread): Make static.
(_threadinfo::call2): Initialize exception handler here.
(_threadinfo::find_tls): Move here.
* exceptions.cc (_threadinfo::find_tls): Move.
* dcrt0.cc (__api_fatal): Add prefix info to message here rather than including
it in every call to function.
* winsup.h (api_fatal): Accommodate above change.
* debug.cc (add_handle): Don't do anything if cygheap not around.
(mark_closed): Ditto.
* dll_init.cc (dll_list::detach): Fix debug output.
* fork.cc (sync_with_child): Ditto.
(vfork): Improve debug output.
* heap.cc (heap_init): Ditto.
* exceptions.cc (try_to_debug): Clarify message when debugger attaches.
2004-01-14 15:45:37 +00:00

335 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 "path.h"
#include "fhandler.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;
}
}