diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index e970723bc..b52a26b8c 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,198 @@ +2004-01-14 Christopher Faylor + + * cygtls.h (_threadinfo::call): Remove regparm declaration to work + around compiler bug. + +2004-01-13 Christopher Faylor + + * 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. + +2004-01-13 Christopher Faylor + + * 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. + +2004-01-12 Christopher Faylor + + * 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. + +2004-01-10 Christopher Faylor + + * 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. + +2004-01-05 Christopher Faylor + + * 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-03 Christopher Faylor * exceptions.cc (_threadinfo::interrupt_now): Avoid double call to diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 742a2e22f..cf15b320d 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -113,7 +113,7 @@ EXTRA_OFILES=$(bupdir1)/libiberty/random.o $(bupdir1)/libiberty/strsignal.o MALLOC_OFILES=@MALLOC_OFILES@ -DLL_IMPORTS:=$(w32api_lib)/libkernel32.a +DLL_IMPORTS:=$(w32api_lib)/libkernel32.a $(w32api_lib)/libadvapi32.a MT_SAFE_OBJECTS:= # Please maintain this list in sorted order, with maximum files per 80 col line @@ -254,6 +254,8 @@ regexec_CFLAGS=-fomit-frame-pointer regfree_CFLAGS=-fomit-frame-pointer shared_CFLAGS:=-fomit-frame-pointer smallprint_CFLAGS:=-fomit-frame-pointer +sysconf_CFLAGS:=-fomit-frame-pointer +uinfo_CFLAGS:=-fomit-frame-pointer endif .PHONY: all force dll_ofiles install all_target install_target all_host install_host \ diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 1628480f8..9cd7f6a4b 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -354,7 +354,7 @@ LoadDLLfunc (LsaQueryInformationPolicy, 12, advapi32) LoadDLLfunc (MakeSelfRelativeSD, 12, advapi32) LoadDLLfunc (OpenProcessToken, 12, advapi32) LoadDLLfunc (OpenThreadToken, 16, advapi32) -LoadDLLfunc (RegCloseKey, 4, advapi32) +// LoadDLLfunc (RegCloseKey, 4, advapi32) LoadDLLfunc (RegCreateKeyExA, 36, advapi32) LoadDLLfunc (RegDeleteKeyA, 8, advapi32) LoadDLLfunc (RegDeleteValueA, 8, advapi32) @@ -515,7 +515,6 @@ LoadDLLfuncEx (Process32Next, 8, kernel32, 1) LoadDLLfuncEx (RegisterServiceProcess, 8, kernel32, 1) LoadDLLfuncEx (SignalObjectAndWait, 16, kernel32, 1) LoadDLLfuncEx (SwitchToThread, 0, kernel32, 1) -LoadDLLfunc (TryEnterCriticalSection, 4, kernel32) LoadDLLfuncEx (waveOutGetNumDevs, 0, winmm, 1) LoadDLLfuncEx (waveOutOpen, 24, winmm, 1) diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 6859e4335..0171f99f6 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -172,6 +172,16 @@ cygheap_fixup_in_child (bool execed) } } +void +init_cygheap::close_ctty () +{ + debug_printf ("closing cygheap->ctty %p", cygheap->ctty); + cygheap->ctty->close (); + if (cygheap->ctty_on_hold == cygheap->ctty) + cygheap->ctty_on_hold = NULL; + cygheap->ctty = NULL; +} + #define pagetrunc(x) ((void *) (((DWORD) (x)) & ~(4096 - 1))) static void *__stdcall @@ -206,6 +216,7 @@ cygheap_init () cygheap->fdtab.init (); if (!cygheap->sigs) sigalloc (); + if (!cygheap->shared_prefix) cygheap->shared_prefix = cstrdup ( wincap.has_terminal_services () diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index 4a56968d8..be5152771 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -19,6 +19,7 @@ enum cygheap_types HEAP_MOUNT, HEAP_SIGS, HEAP_ARCHETYPES, + HEAP_TLS, HEAP_1_START, HEAP_1_STR, HEAP_1_ARGV, @@ -263,7 +264,10 @@ struct init_cygheap fhandler_tty_slave *ctty; /* Current tty */ fhandler_tty_slave *ctty_on_hold; + struct _threadinfo **threadlist; + size_t sthreads; int open_fhs; + void close_ctty (); }; #define CYGHEAPSIZE (sizeof (init_cygheap) + (20000 * sizeof (fhandler_union)) + (5 * 65536)) @@ -282,7 +286,7 @@ class cygheap_fdmanip virtual ~cygheap_fdmanip () { if (locked) - ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "cygheap_fdmanip"); + cygheap->fdtab.unlock (); } void release () { @@ -308,7 +312,7 @@ class cygheap_fdnew : public cygheap_fdmanip cygheap_fdnew (int seed_fd = -1, bool lockit = true) { if (lockit) - SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "cygheap_fdnew"); + cygheap->fdtab.lock (); if (seed_fd < 0) fd = cygheap->fdtab.find_unused_handle (); else @@ -322,7 +326,7 @@ class cygheap_fdnew : public cygheap_fdmanip { set_errno (EMFILE); if (lockit) - ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "cygheap_fdnew"); + cygheap->fdtab.unlock (); locked = false; } } @@ -335,7 +339,7 @@ class cygheap_fdget : public cygheap_fdmanip cygheap_fdget (int fd, bool lockit = false, bool do_set_errno = true) { if (lockit) - SetResourceLock (LOCK_FD_LIST, READ_LOCK, "cygheap_fdget"); + cygheap->fdtab.lock (); if (fd >= 0 && fd < (int) cygheap->fdtab.size && *(fh = cygheap->fdtab + fd) != NULL) { @@ -348,7 +352,7 @@ class cygheap_fdget : public cygheap_fdmanip if (do_set_errno) set_errno (EBADF); if (lockit) - ReleaseResourceLock (LOCK_FD_LIST, READ_LOCK, "cygheap_fdget"); + cygheap->fdtab.unlock (); locked = false; } } diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc index 16f629634..e83019663 100644 --- a/winsup/cygwin/cygthread.cc +++ b/winsup/cygwin/cygthread.cc @@ -32,12 +32,6 @@ bool NO_COPY cygthread::exiting; DWORD WINAPI cygthread::stub (VOID *arg) { - exception_list except_entry; - /* Initialize this thread's ability to respond to things like - SIGSEGV or SIGFPE. */ - init_exceptions (&except_entry); - _my_tls.remove (); // Remove me from signal chain -- not signalable. - cygthread *info = (cygthread *) arg; if (info->arg == cygself) { @@ -46,7 +40,7 @@ cygthread::stub (VOID *arg) CloseHandle (info->ev); CloseHandle (info->thread_sync); } - info->ev = info->thread_sync = info->stack_ptr = NULL; + info->ev = info->thread_sync = info->stack_ptr = NULL; } else { @@ -57,6 +51,7 @@ cygthread::stub (VOID *arg) info->thread_sync = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL); } } + while (1) { if (!info->__name) @@ -92,12 +87,6 @@ cygthread::stub (VOID *arg) DWORD WINAPI cygthread::simplestub (VOID *arg) { - exception_list except_entry; - /* Initialize this thread's ability to respond to things like - SIGSEGV or SIGFPE. */ - init_exceptions (&except_entry); - _my_tls.remove (); // Remove me from signal chain -- not signalable. - cygthread *info = (cygthread *) arg; info->stack_ptr = &arg; info->ev = info->h; diff --git a/winsup/cygwin/cygthread.h b/winsup/cygwin/cygthread.h index eb2eb9a8f..76604b471 100644 --- a/winsup/cygwin/cygthread.h +++ b/winsup/cygwin/cygthread.h @@ -19,12 +19,10 @@ class cygthread VOID *arg; bool is_freerange; static bool exiting; - static void stub2 (void *, void *); - static DWORD WINAPI simplestub (VOID *); - static void simplestub2 (void *, void *); void terminate_thread (); public: static DWORD WINAPI stub (VOID *); + static DWORD WINAPI simplestub (VOID *); static DWORD main_thread_id; static const char * name (DWORD = 0); cygthread (LPTHREAD_START_ROUTINE, LPVOID, const char *); @@ -43,7 +41,6 @@ class cygthread (void) CloseHandle (h); h = NULL; } - }; #define cygself NULL diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index 2734cf536..5c9fa615f 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -1,6 +1,6 @@ -/* cygtls.h +/* cygtls.cc - Copyright 2003 Red Hat, Inc. + Copyright 2003, 2004 Red Hat, Inc. This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for @@ -11,11 +11,48 @@ details. */ #include "cygtls.h" #include "assert.h" #include +#include +#include "exceptions.h" +#include "sync.h" +#include "cygerrno.h" +#include "path.h" +#include "fhandler.h" +#include "dtable.h" +#include "cygheap.h" +#include "cygthread.h" -static _threadinfo NO_COPY dummy_thread; -_threadinfo NO_COPY *_last_thread = &dummy_thread; +class sentry +{ + static muto *lock; + int destroy; +public: + void init (); + bool acquired () {return lock->acquired ();} + sentry () {destroy = 0;} + sentry (DWORD wait) {destroy = lock->acquire (wait);} + ~sentry () {if (destroy) lock->release ();} + friend void _threadinfo::init (); +}; -CRITICAL_SECTION NO_COPY _threadinfo::protect_linked_list; +muto NO_COPY *sentry::lock; + +static size_t NO_COPY nthreads; + +#define THREADLIST_CHUNK 256 + +void +_threadinfo::init () +{ + if (cygheap->threadlist) + memset (cygheap->threadlist, 0, cygheap->sthreads * sizeof (cygheap->threadlist[0])); + else + { + cygheap->sthreads = THREADLIST_CHUNK; + cygheap->threadlist = (_threadinfo **) ccalloc (HEAP_TLS, cygheap->sthreads, + sizeof (cygheap->threadlist[0])); + } + new_muto1 (sentry::lock, sentry_lock); +} void _threadinfo::set_state (bool is_exception) @@ -32,7 +69,6 @@ _threadinfo::reset_exception () debug_printf ("resetting stack after an exception stack %p, stackptr %p", stack, stackptr); #endif set_state (false); - stackptr--; } } @@ -47,22 +83,22 @@ _threadinfo::call (DWORD (*func) (void *, void *), void *arg) void _threadinfo::call2 (DWORD (*func) (void *, void *), void *arg, void *buf) { - _my_tls.init_thread (buf); - ExitThread (func (arg, buf)); + exception_list except_entry; + /* Initialize this thread's ability to respond to things like + SIGSEGV or SIGFPE. */ + init_exceptions (&except_entry); + _my_tls.init_thread (buf, func); + DWORD res = func (arg, buf); + _my_tls.remove (INFINITE); + ExitThread (res); } void -_threadinfo::init () -{ - InitializeCriticalSection (&protect_linked_list); -} - -void -_threadinfo::init_thread (void *x) +_threadinfo::init_thread (void *x, DWORD (*func) (void *, void *)) { if (x) { - memset (this, 0, sizeof (*this)); + memset (this, 0, CYGTLS_PADSIZE); stackptr = stack; if (_GLOBAL_REENT) { @@ -76,30 +112,40 @@ _threadinfo::init_thread (void *x) locals.process_logmask = LOG_UPTO (LOG_DEBUG); } - EnterCriticalSection (&protect_linked_list); - prev = _last_thread; - _last_thread->next = this; - _last_thread = this; - LeaveCriticalSection (&protect_linked_list); - set_state (false); errno_addr = &(local_clib._errno); + + if ((void *) func == (void *) cygthread::stub + || (void *) func == (void *) cygthread::simplestub) + return; + + sentry here (INFINITE); + if (nthreads >= cygheap->sthreads) + { + cygheap->threadlist = (_threadinfo **) + crealloc (cygheap->threadlist, (cygheap->sthreads += THREADLIST_CHUNK) + * sizeof (cygheap->threadlist[0])); + memset (cygheap->threadlist + nthreads, 0, THREADLIST_CHUNK * sizeof (cygheap->threadlist[0])); + } + + cygheap->threadlist[nthreads++] = this; } void -_threadinfo::remove () +_threadinfo::remove (DWORD wait) { - EnterCriticalSection (&protect_linked_list); - if (prev) + debug_printf ("wait %p\n", wait); + sentry here (wait); + if (here.acquired ()) { - prev->next = next; - if (next) - next->prev = prev; - if (this == _last_thread) - _last_thread = prev; - prev = next = NULL; + for (size_t i = 0; i < nthreads; i++) + if (&_my_tls == cygheap->threadlist[i]) + { + if (i < --nthreads) + cygheap->threadlist[i] = cygheap->threadlist[nthreads]; + break; + } } - LeaveCriticalSection (&protect_linked_list); } void @@ -123,3 +169,48 @@ _threadinfo::pop () return res; } +#define BAD_IX ((size_t) -1) +static size_t NO_COPY threadlist_ix = BAD_IX; + +_threadinfo * +_threadinfo::find_tls (int sig) +{ + debug_printf ("sig %d\n", sig); + sentry here (INFINITE); + __asm__ volatile (".equ _threadlist_exception_return,."); + _threadinfo *res = NULL; + for (threadlist_ix = 0; threadlist_ix < nthreads; threadlist_ix++) + if (sigismember (&(cygheap->threadlist[threadlist_ix]->sigwait_mask), sig)) + { + res = cygheap->threadlist[threadlist_ix]; + break; + } + threadlist_ix = BAD_IX; + return res; +} + +extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD); +static int +handle_threadlist_exception (EXCEPTION_RECORD *e, void *frame, CONTEXT *, void *) +{ + small_printf ("in handle_threadlist_exception!\n"); + if (e->ExceptionCode != STATUS_ACCESS_VIOLATION) + return 1; + + sentry here; + if (threadlist_ix != BAD_IX || !here.acquired ()) + return 1; + + extern void *threadlist_exception_return; + cygheap->threadlist[threadlist_ix]->remove (INFINITE); + threadlist_ix = 0; + RtlUnwind (frame, threadlist_exception_return, e, 0); + return 0; +} + +void +_threadinfo::init_threadlist_exceptions (exception_list *el) +{ + extern void init_exception_handler (exception_list *, exception_handler *); + init_exception_handler (el, handle_threadlist_exception); +} diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h index f11c65b7e..779e42b89 100644 --- a/winsup/cygwin/cygtls.h +++ b/winsup/cygwin/cygtls.h @@ -28,7 +28,7 @@ details. */ # define UNLEN 256 #endif -#define TLS_STACK_SIZE 1024 +#define TLS_STACK_SIZE 256 #pragma pack(push,4) struct _local_storage @@ -110,15 +110,16 @@ struct _threadinfo __stack_t *stackptr; int sig; __stack_t stack[TLS_STACK_SIZE]; + unsigned padding[0]; /*gentls_offsets*/ static CRITICAL_SECTION protect_linked_list; static void init (); - void init_thread (void *) __attribute__ ((regparm (2))); - static void call (DWORD (*) (void *, void *), void *) __attribute__ ((regparm (3))); + void init_thread (void *, DWORD (*) (void *, void *)); + static void call (DWORD (*) (void *, void *), void *); static void call2 (DWORD (*) (void *, void *), void *, void *) __attribute__ ((regparm (3))); static struct _threadinfo *find_tls (int sig); - void remove (); + void remove (DWORD); void push (__stack_t, bool = false); __stack_t pop (); bool isinitialized () {return initialized == CYGTLS_INITIALIZED || initialized == CYGTLS_EXCEPTION;} @@ -128,6 +129,7 @@ struct _threadinfo __attribute__((regparm(3))); void __stdcall interrupt_setup (int sig, void *handler, struct sigaction& siga, __stack_t retaddr) __attribute__((regparm(3))); + void init_threadlist_exceptions (struct _exception_list *); operator HANDLE () const {return tid->win32_obj_id;} /*gentls_offsets*/ }; @@ -140,5 +142,5 @@ extern _threadinfo *_main_tls; #define __getreent() (&_my_tls.local_clib) -#define CYGTLS_PADSIZE (sizeof (_threadinfo)) +const int CYGTLS_PADSIZE = (((char *) _main_tls->padding) - ((char *) _main_tls)); #endif /*_CYGTLS_H*/ diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index f97c0f927..3d6b7a89b 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -35,6 +35,7 @@ details. */ #include "dll_init.h" #include "cygthread.h" #include "sync.h" +#include "heap.h" #define MAX_AT_FILE_LEVEL 10 @@ -55,11 +56,13 @@ bool strip_title_path; bool allow_glob = true; codepage_type current_codepage = ansi_cp; -static NO_COPY int mypid = 0; int __argc_safe; int _declspec(dllexport) __argc; char _declspec(dllexport) **__argv; -vfork_save NO_COPY *main_vfork = NULL; +vfork_save NO_COPY *main_vfork; + +static int NO_COPY envc; +char NO_COPY **envp; extern "C" void __sinit (_reent *); @@ -519,41 +522,127 @@ alloc_stack (child_info_fork *ci) return; } -/* Take over from libc's crt0.o and start the application. Note the - various special cases when Cygwin DLL is being runtime loaded (as - opposed to being link-time loaded by Cygwin apps) from a non - cygwin app via LoadLibrary. */ -static void -dll_crt0_1 (char *) +#ifdef DEBUGGING +void +break_here () { - /* According to onno@stack.urc.tue.nl, the exception handler record must - be on the stack. */ - /* FIXME: Verify forked children get their exception handler set up ok. */ - exception_list cygwin_except_entry; + debug_printf ("break here"); +} +#endif - /* Initialize SIGSEGV handling, etc. */ - init_exceptions (&cygwin_except_entry); +static void +initial_env () +{ + char buf[CYG_MAX_PATH + 1]; +#ifdef DEBUGGING + DWORD len; + if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1)) + { + DWORD ms = atoi (buf); + buf[0] = '\0'; + len = GetModuleFileName (NULL, buf, CYG_MAX_PATH); + console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf); + while (ms--) + Sleep (1); + } + if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1)) + { + char buf1[CYG_MAX_PATH + 1]; + len = GetModuleFileName (NULL, buf1, CYG_MAX_PATH); + strlwr (buf1); + strlwr (buf); + char *p = strchr (buf, ':'); + if (!p) + p = (char *) "gdb.exe -nw"; + else + *p++ = '\0'; + if (strstr (buf1, buf)) + { + error_start_init (p); + try_to_debug (); + break_here (); + } + } +#endif - /* Set the os_being_run global. */ + if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1)) + _cygwin_testing = 1; +} + +void __stdcall +dll_crt0_0 () +{ wincap.init (); + initial_env (); + + char zeros[sizeof (child_proc_info->zero)] = {0}; + + init_console_handler (); + init_global_security (); + if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (), + GetCurrentProcess (), &hMainProc, 0, FALSE, + DUPLICATE_SAME_ACCESS)) + hMainProc = GetCurrentProcess (); + + DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc, + &hMainThread, 0, false, DUPLICATE_SAME_ACCESS); + + (void) SetErrorMode (SEM_FAILCRITICALERRORS); + + STARTUPINFO si; + GetStartupInfo (&si); + child_proc_info = (child_info *) si.lpReserved2; + + int mypid = 0; + if (si.cbReserved2 < EXEC_MAGIC_SIZE || !child_proc_info + || memcmp (child_proc_info->zero, zeros, + sizeof (child_proc_info->zero)) != 0) + child_proc_info = NULL; + else + { + if ((child_proc_info->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC) + multiple_cygwin_problem ("proc", child_proc_info->intro, 0); + else if (child_proc_info->intro == PROC_MAGIC_GENERIC + && child_proc_info->magic != CHILD_INFO_MAGIC) + multiple_cygwin_problem ("proc", child_proc_info->magic, + CHILD_INFO_MAGIC); + else if (child_proc_info->cygheap != (void *) &_cygheap_start) + multiple_cygwin_problem ("cygheap", (DWORD) child_proc_info->cygheap, + (DWORD) &_cygheap_start); + unsigned should_be_cb = 0; + switch (child_proc_info->type) + { + case _PROC_FORK: + user_data->forkee = child_proc_info->cygpid; + should_be_cb = sizeof (child_info_fork); + /* fall through */; + case _PROC_SPAWN: + case _PROC_EXEC: + if (!should_be_cb) + should_be_cb = sizeof (child_info); + if (should_be_cb != child_proc_info->cb) + multiple_cygwin_problem ("proc size", child_proc_info->cb, should_be_cb); + else if (sizeof (fhandler_union) != child_proc_info->fhandler_union_cb) + multiple_cygwin_problem ("fhandler size", child_proc_info->fhandler_union_cb, sizeof (fhandler_union)); + else + { + cygwin_user_h = child_proc_info->user_h; + mypid = child_proc_info->cygpid; + break; + } + default: + system_printf ("unknown exec type %d", child_proc_info->type); + /* intentionally fall through */ + case _PROC_WHOOPS: + child_proc_info = NULL; + break; + } + } + device::init (); - check_sanity_and_sync (user_data); - - do_global_ctors (&__CTOR_LIST__, 1); - - /* Nasty static stuff needed by newlib -- point to a local copy of - the reent stuff. - Note: this MUST be done here (before the forkee code) as the - fork copy code doesn't copy the data in libccrt0.cc (that's why we - pass in the per_process struct into the .dll from libccrt0). */ - - user_data->resourcelocks->Init (); - user_data->threadinterface->Init (); - winpids::init (); - - int envc = 0; - char **envp = NULL; + do_global_ctors (&__CTOR_LIST__, 1); + cygthread::init (); if (!child_proc_info) memory_init (); @@ -591,6 +680,7 @@ dll_crt0_1 (char *) __argv = spawn_info->moreinfo->argv; envp = spawn_info->moreinfo->envp; envc = spawn_info->moreinfo->envc; + envp = spawn_info->moreinfo->envp; cygheap->fdtab.fixup_after_exec (spawn_info->parent); signal_fixup_after_exec (); CloseHandle (spawn_info->parent); @@ -607,9 +697,44 @@ dll_crt0_1 (char *) CloseHandle (child_proc_info->pppid_handle); } + _threadinfo::init (); + + /* Initialize events */ + events_init (); + + /* Init global well known SID objects */ + cygsid::init (); + cygheap->cwd.init (); +} + +/* Take over from libc's crt0.o and start the application. Note the + various special cases when Cygwin DLL is being runtime loaded (as + opposed to being link-time loaded by Cygwin apps) from a non + cygwin app via LoadLibrary. */ +static void +dll_crt0_1 (char *) +{ + /* According to onno@stack.urc.tue.nl, the exception handler record must + be on the stack. */ + /* FIXME: Verify forked children get their exception handler set up ok. */ + exception_list cygwin_except_entry; + + check_sanity_and_sync (user_data); + malloc_init (); + + /* Initialize SIGSEGV handling, etc. */ + init_exceptions (&cygwin_except_entry); + + /* Nasty static stuff needed by newlib -- point to a local copy of + the reent stuff. + Note: this MUST be done here (before the forkee code) as the + fork copy code doesn't copy the data in libccrt0.cc (that's why we + pass in the per_process struct into the .dll from libccrt0). */ + + user_data->resourcelocks->Init (); + user_data->threadinterface->Init (); ProtectHandle (hMainProc); ProtectHandle (hMainThread); - cygthread::init (); /* Initialize pthread mainthread when not forked and it is safe to call new, otherwise it is reinitalized in fixup_after_fork */ @@ -629,12 +754,6 @@ dll_crt0_1 (char *) cygheap->fdtab.vfork_child_fixup (); - (void) SetErrorMode (SEM_FAILCRITICALERRORS); - - /* Initialize events. */ - events_init (); - - cygheap->cwd.init (); main_vfork = vfork_storage.create (); cygbench ("pre-forkee"); @@ -663,9 +782,6 @@ dll_crt0_1 (char *) } #endif - /* Init global well known SID objects */ - cygsid::init (); - /* Initialize our process table entry. */ pinfo_init (envp, envc); @@ -773,60 +889,13 @@ dll_crt0_1 (char *) exit (user_data->main (__argc, __argv, *user_data->envptr)); } -#ifdef DEBUGGING -void -break_here () -{ - debug_printf ("break here"); -} -#endif - -void -initial_env () -{ - char buf[CYG_MAX_PATH + 1]; -#ifdef DEBUGGING - DWORD len; - if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1)) - { - DWORD ms = atoi (buf); - buf[0] = '\0'; - len = GetModuleFileName (NULL, buf, CYG_MAX_PATH); - console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf); - Sleep (ms); - } - if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1)) - { - char buf1[CYG_MAX_PATH + 1]; - len = GetModuleFileName (NULL, buf1, CYG_MAX_PATH); - strlwr (buf1); - strlwr (buf); - char *p = strchr (buf, ':'); - if (!p) - p = (char *) "gdb.exe -nw"; - else - *p++ = '\0'; - if (strstr (buf1, buf)) - { - error_start_init (p); - try_to_debug (); - break_here (); - } - } -#endif - - if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1)) - _cygwin_testing = 1; -} - struct _reent * initialize_main_tls (char *padding) { if (!_main_tls) { - _threadinfo::init (); _main_tls = &_my_tls; - _main_tls->init_thread (padding); + _main_tls->init_thread (padding, NULL); } return &_main_tls->local_clib; } @@ -836,81 +905,31 @@ initialize_main_tls (char *padding) UPTR is a pointer to global data that lives on the libc side of the line [if one distinguishes the application from the dll]. */ - + extern "C" void __stdcall _dll_crt0 () { - initial_env (); - char zeros[max (CYGTLS_PADSIZE, sizeof (child_proc_info->zero))] = {0}; - static NO_COPY STARTUPINFO si; + extern HANDLE sync_startup; + if (sync_startup) + { + (void) WaitForSingleObject (sync_startup, INFINITE); + CloseHandle (sync_startup); + } main_environ = user_data->envptr; *main_environ = NULL; - init_console_handler (); - init_global_security (); - if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (), - GetCurrentProcess (), &hMainProc, 0, FALSE, - DUPLICATE_SAME_ACCESS)) - hMainProc = GetCurrentProcess (); + if (child_proc_info && child_proc_info->type == _PROC_FORK) + user_data->forkee = child_proc_info->cygpid; - DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc, - &hMainThread, 0, false, DUPLICATE_SAME_ACCESS); - - GetStartupInfo (&si); - child_proc_info = (child_info *) si.lpReserved2; - if (si.cbReserved2 < EXEC_MAGIC_SIZE || !child_proc_info - || memcmp (child_proc_info->zero, zeros, - sizeof (child_proc_info->zero)) != 0) - child_proc_info = NULL; - else - { - if ((child_proc_info->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC) - multiple_cygwin_problem ("proc", child_proc_info->intro, 0); - else if (child_proc_info->intro == PROC_MAGIC_GENERIC - && child_proc_info->magic != CHILD_INFO_MAGIC) - multiple_cygwin_problem ("proc", child_proc_info->magic, - CHILD_INFO_MAGIC); - else if (child_proc_info->cygheap != (void *) &_cygheap_start) - multiple_cygwin_problem ("cygheap", (DWORD) child_proc_info->cygheap, - (DWORD) &_cygheap_start); - unsigned should_be_cb = 0; - switch (child_proc_info->type) - { - case _PROC_FORK: - user_data->forkee = child_proc_info->cygpid; - should_be_cb = sizeof (child_info_fork); - /* fall through */; - case _PROC_SPAWN: - case _PROC_EXEC: - if (!should_be_cb) - should_be_cb = sizeof (child_info); - if (should_be_cb != child_proc_info->cb) - multiple_cygwin_problem ("proc size", child_proc_info->cb, should_be_cb); - else if (sizeof (fhandler_union) != child_proc_info->fhandler_union_cb) - multiple_cygwin_problem ("fhandler size", child_proc_info->fhandler_union_cb, sizeof (fhandler_union)); - else - { - cygwin_user_h = child_proc_info->user_h; - mypid = child_proc_info->cygpid; - break; - } - default: - system_printf ("unknown exec type %d", child_proc_info->type); - /* intentionally fall through */ - case _PROC_WHOOPS: - child_proc_info = NULL; - break; - } - } - + char padding[CYGTLS_PADSIZE]; _impure_ptr = &reent_data; _impure_ptr->_stdin = &_impure_ptr->__sf[0]; _impure_ptr->_stdout = &_impure_ptr->__sf[1]; _impure_ptr->_stderr = &_impure_ptr->__sf[2]; _impure_ptr->_current_locale = "C"; - initialize_main_tls (zeros); - dll_crt0_1 (zeros); + initialize_main_tls (padding); + dll_crt0_1 (padding); } void @@ -970,6 +989,7 @@ do_exit (int status) } EnterCriticalSection (&exit_lock); + muto::set_exiting_thread (); if (exit_state < ES_EVENTS_TERMINATE) { exit_state = ES_EVENTS_TERMINATE; @@ -1090,7 +1110,8 @@ __api_fatal (const char *fmt, ...) va_list ap; va_start (ap, fmt); - __small_vsprintf (buf, fmt, ap); + int n = __small_sprintf (buf, "%P (%u): *** ", cygwin_pid (GetCurrentProcessId ())); + __small_vsprintf (buf + n, fmt, ap); va_end (ap); strcat (buf, "\n"); int len = strlen (buf); diff --git a/winsup/cygwin/debug.cc b/winsup/cygwin/debug.cc index 4f1d6dfa3..05b53cf33 100644 --- a/winsup/cygwin/debug.cc +++ b/winsup/cygwin/debug.cc @@ -112,6 +112,9 @@ add_handle (const char *func, int ln, HANDLE h, const char *name, bool inh) handle_list *hl; lock_debug here; + if (!cygheap) + return; + if ((hl = find_handle (h))) { hl = hl->next; @@ -172,6 +175,9 @@ mark_closed (const char *func, int ln, HANDLE h, const char *name, bool force) handle_list *hl; lock_debug here; + if (!cygheap) + return true; + if ((hl = find_handle (h)) && !force) { hl = hl->next; diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc index 2bc987fc1..8a25b7d8c 100644 --- a/winsup/cygwin/dlfcn.cc +++ b/winsup/cygwin/dlfcn.cc @@ -83,8 +83,6 @@ get_full_path_of_dll (const char* str, char *name) void * dlopen (const char *name, int) { - SetResourceLock (LOCK_DLL_LIST, READ_LOCK | WRITE_LOCK, "dlopen"); - void *ret; if (name == NULL) @@ -108,7 +106,6 @@ dlopen (const char *name, int) set_dl_error ("dlopen"); debug_printf ("ret %p", ret); - ReleaseResourceLock (LOCK_DLL_LIST, READ_LOCK | WRITE_LOCK, "dlopen"); return ret; } @@ -125,8 +122,6 @@ dlsym (void *handle, const char *name) int dlclose (void *handle) { - SetResourceLock (LOCK_DLL_LIST, READ_LOCK | WRITE_LOCK, "dlclose"); - int ret = -1; void *temphandle = (void *) GetModuleHandle (NULL); if (temphandle == handle || FreeLibrary ((HMODULE) handle)) @@ -134,8 +129,6 @@ dlclose (void *handle) if (ret) set_dl_error ("dlclose"); CloseHandle ((HMODULE) temphandle); - - ReleaseResourceLock (LOCK_DLL_LIST, READ_LOCK | WRITE_LOCK, "dlclose"); return ret; } diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc index 1bfd61cf9..14bfe936a 100644 --- a/winsup/cygwin/dll_init.cc +++ b/winsup/cygwin/dll_init.cc @@ -195,7 +195,7 @@ dll_list::detach (void *retaddr) if (d->handle != h) continue; else if (d->count <= 0) - system_printf ("WARNING: try to detach an already detached dll ..."); + system_printf ("WARNING: trying to detach an already detached dll ..."); else if (--d->count == 0) { d->p.run_dtors (); diff --git a/winsup/cygwin/dll_init.sgml b/winsup/cygwin/dll_init.sgml index 2c37a22a7..38070390c 100644 --- a/winsup/cygwin/dll_init.sgml +++ b/winsup/cygwin/dll_init.sgml @@ -3,11 +3,9 @@ cygwin_detach_dll - extern "C" void cygwin_detach_dll int dll_index - diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index 141e17382..cd41cb925 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -33,19 +33,21 @@ details. */ #include "ntdll.h" #include "tty.h" +static const char NO_COPY unknown_file[] = "some disk file"; + static const NO_COPY DWORD std_consts[] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE}; static const char *handle_to_fn (HANDLE, char *); -static const char NO_COPY unknown_file[] = "some disk file"; - /* Set aside space for the table of fds */ void -dtable_init (void) +dtable_init () { if (!cygheap->fdtab.size) cygheap->fdtab.extend (NOFILE_INCR); + cygheap->fdtab.init_lock (); + } void __stdcall @@ -57,6 +59,12 @@ set_std_handle (int fd) SetStdHandle (std_consts[fd], cygheap->fdtab[fd]->get_output_handle ()); } +void +dtable::init_lock () +{ + new_muto (lock_cs); +} + int dtable::extend (int howmuch) { @@ -490,7 +498,7 @@ dtable::dup2 (int oldfd, int newfd) MALLOC_CHECK; debug_printf ("dup2 (%d, %d)", oldfd, newfd); - SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup"); + lock (); if (not_open (oldfd)) { @@ -539,7 +547,7 @@ dtable::dup2 (int oldfd, int newfd) done: MALLOC_CHECK; - ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup"); + unlock (); syscall_printf ("%d = dup2 (%d, %d)", res, oldfd, newfd); return res; @@ -548,7 +556,7 @@ done: fhandler_fifo * dtable::find_fifo (ATOM hill) { - SetResourceLock (LOCK_FD_LIST, READ_LOCK, "dup"); + lock (); for (unsigned i = 0; i < size; i++) { fhandler_base *fh = fds[i]; @@ -614,7 +622,7 @@ dtable::select_except (int fd, select_record *s) void dtable::fixup_before_fork (DWORD target_proc_id) { - SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "fixup_before_fork"); + lock (); fhandler_base *fh; for (size_t i = 0; i < size; i++) if ((fh = fds[i]) != NULL) @@ -622,13 +630,13 @@ dtable::fixup_before_fork (DWORD target_proc_id) debug_printf ("fd %d (%s)", i, fh->get_name ()); fh->fixup_before_fork_exec (target_proc_id); } - ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "fixup_before_fork"); + unlock (); } void dtable::fixup_before_exec (DWORD target_proc_id) { - SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "fixup_before_exec"); + lock (); fhandler_base *fh; for (size_t i = 0; i < size; i++) if ((fh = fds[i]) != NULL && !fh->get_close_on_exec ()) @@ -636,18 +644,18 @@ dtable::fixup_before_exec (DWORD target_proc_id) debug_printf ("fd %d (%s)", i, fh->get_name ()); fh->fixup_before_fork_exec (target_proc_id); } - ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "fixup_before_exec"); + unlock (); } void dtable::set_file_pointers_for_exec () { - SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "set_file_pointers_for_exec"); + lock (); fhandler_base *fh; for (size_t i = 0; i < size; i++) if ((fh = fds[i]) != NULL && fh->get_flags () & O_APPEND) SetFilePointer (fh->get_handle (), 0, 0, FILE_END); - ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "fixup_before_exec"); + unlock (); } void @@ -655,6 +663,7 @@ dtable::fixup_after_exec (HANDLE parent) { first_fd_for_open = 0; fhandler_base *fh; + cygheap->fdtab.init_lock (); for (size_t i = 0; i < size; i++) if ((fh = fds[i]) != NULL) { @@ -680,6 +689,7 @@ void dtable::fixup_after_fork (HANDLE parent) { fhandler_base *fh; + cygheap->fdtab.init_lock (); for (size_t i = 0; i < size; i++) if ((fh = fds[i]) != NULL) { @@ -699,7 +709,7 @@ int dtable::vfork_child_dup () { fhandler_base **newtable; - SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup"); + lock (); newtable = (fhandler_base **) ccalloc (HEAP_ARGV, size, sizeof (fds[0])); int res = 1; @@ -731,21 +741,21 @@ out: /* Restore impersonation */ cygheap->user.reimpersonate (); - ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup"); + unlock (); return 1; } void dtable::vfork_parent_restore () { - SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "restore"); + lock (); close_all_files (); fhandler_base **deleteme = fds; fds = fds_on_hold; fds_on_hold = NULL; cfree (deleteme); - ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "restore"); + unlock (); cygheap->ctty = cygheap->ctty_on_hold; // revert if (cygheap->ctty) diff --git a/winsup/cygwin/dtable.h b/winsup/cygwin/dtable.h index 0b2db916b..573467d01 100644 --- a/winsup/cygwin/dtable.h +++ b/winsup/cygwin/dtable.h @@ -12,6 +12,7 @@ details. */ #define NOFILE_INCR 32 #include "thread.h" +#include "sync.h" class suffix_info; class fhandler_fifo; @@ -19,6 +20,7 @@ class fhandler_fifo; #define BFH_OPTS (PC_NULLEMPTY | PC_FULL | PC_POSIX) class dtable { + muto *lock_cs; fhandler_base **fds; fhandler_base **fds_on_hold; fhandler_base **archetypes; @@ -27,6 +29,9 @@ class dtable static const int initial_archetype_size = 8; int first_fd_for_open; int cnt_need_fixup_before; + void lock () {lock_cs->acquire ();} + void unlock () {lock_cs->release ();} + void init_lock (); public: size_t size; @@ -50,11 +55,9 @@ public: void fixup_after_fork (HANDLE); inline int not_open (int fd) { - SetResourceLock (LOCK_FD_LIST, READ_LOCK, "not_open"); - + lock (); int res = fd < 0 || fd >= (int) size || fds[fd] == NULL; - - ReleaseResourceLock (LOCK_FD_LIST, READ_LOCK, "not open"); + unlock (); return res; } int find_unused_handle (int start); @@ -76,6 +79,11 @@ public: fhandler_base *find_archetype (device& dev); fhandler_base **add_archetype (); void delete_archetype (fhandler_base *); + friend void dtable_init (); + friend void __stdcall close_all_files (); + friend class cygheap_fdmanip; + friend class cygheap_fdget; + friend class cygheap_fdnew; }; fhandler_base *build_fh_dev (const device&, const char * = NULL); diff --git a/winsup/cygwin/dtable.sgml b/winsup/cygwin/dtable.sgml index 5e807883b..9f292ee73 100644 --- a/winsup/cygwin/dtable.sgml +++ b/winsup/cygwin/dtable.sgml @@ -3,7 +3,6 @@ cygwin_attach_handle_to_fd - extern "C" int cygwin_attach_handle_to_fd char *name @@ -11,7 +10,6 @@ HANDLE handle int bin int access - This function can be used to turn a Win32 "handle" into a diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 669b516ab..597c58e47 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -98,18 +98,22 @@ NO_COPY static struct // of code that handles exceptions. The x86 on the other hand uses segment // register fs, offset 0 to point to the current exception handler. -asm (".equ __except_list,0"); +extern exception_list *_except_list asm ("%fs:0"); -extern exception_list *_except_list asm ("%fs:__except_list"); - -static void -init_exception_handler (exception_list *el) +void +init_exception_handler (exception_list *el, exception_handler *eh) { - el->handler = handle_exceptions; + el->handler = eh; el->prev = _except_list; _except_list = el; } +extern "C" void +init_exceptions (exception_list *el) +{ + init_exception_handler (el, handle_exceptions); +} + void init_console_handler () { @@ -118,12 +122,6 @@ init_console_handler () system_printf ("SetConsoleCtrlHandler failed, %E"); } -extern "C" void -init_exceptions (exception_list *el) -{ - init_exception_handler (el); -} - extern "C" void error_start_init (const char *buf) { @@ -363,6 +361,8 @@ try_to_debug (bool waitloop) } } + small_printf ("*** starting debugger for pid %u\n", + cygwin_pid (GetCurrentProcessId ())); BOOL dbg; dbg = CreateProcess (NULL, debugger_command, @@ -383,9 +383,9 @@ try_to_debug (bool waitloop) return 1; SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE); while (!being_debugged ()) - Sleep (0); - Sleep (2000); - small_printf ("*** continuing from debugger call\n"); + low_priority_sleep (0); + small_printf ("*** continuing pid %u from debugger call\n", + cygwin_pid (GetCurrentProcessId ())); } SetThreadPriority (GetCurrentThread (), prio); @@ -615,7 +615,7 @@ sig_handle_tty_stop (int sig) } } -int +bool interruptible (DWORD pc) { int res; @@ -633,11 +633,11 @@ interruptible (DWORD pc) GetThreadContext. These resolve to a strange allocation base. These should *never* be treated as interruptible. */ if (!h || m.State != MEM_COMMIT) - res = 0; + res = false; else if (h == user_data->hmodule) - res = 1; + res = true; else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2)) - res = 0; + res = false; else res = !strncasematch (windows_system_directory, checkdir, windows_system_directory_length); @@ -666,7 +666,8 @@ _threadinfo::interrupt_setup (int sig, void *handler, /* Clear any waiting threads prior to dispatching to handler function */ int res = SetEvent (signal_arrived); // For an EINTR case proc_subproc (PROC_CLEARWAIT, 1); - sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res); + sigproc_printf ("armed signal_arrived %p, sig %d, res %d", signal_arrived, + sig, res); } bool @@ -762,26 +763,16 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls) // FIXME - add check for reentering of DLL here - muto *m; - /* FIXME: Make multi-thread aware */ - for (m = muto_start.next; m != NULL; m = m->next) - if (m->unstable () || m->owner () == cygthread::main_thread_id) - { - sigproc_printf ("suspended thread owns a muto (%s)", m->name); - goto resume_thread; - } - cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; if (!GetThreadContext (hth, &cx)) system_printf ("couldn't get context of main thread, %E"); else if (interruptible (cx.Eip)) interrupted = tls->interrupt_now (&cx, sig, handler, siga); - resume_thread: res = ResumeThread (hth); - if (interrupted) break; + sigproc_printf ("couldn't interrupt. trying again."); low_priority_sleep (0); } @@ -801,7 +792,7 @@ static BOOL WINAPI ctrl_c_handler (DWORD type) { static bool saw_close; - _my_tls.remove (); + _my_tls.remove (INFINITE); /* Return FALSE to prevent an "End task" dialog box from appearing for each Cygwin process window that's open when the computer @@ -892,19 +883,6 @@ set_signal_mask (sigset_t newmask, sigset_t oldmask) return; } -extern _threadinfo *_last_thread; - -_threadinfo * -_threadinfo::find_tls (int sig) -{ - EnterCriticalSection (&protect_linked_list); - for (_threadinfo *t = _last_thread; t ; t = t->prev) - if (sigismember (&t->sigwait_mask, sig)) - return t; - LeaveCriticalSection (&protect_linked_list); - return NULL; -} - int __stdcall sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls) { @@ -924,15 +902,15 @@ sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls) int rc = 1; bool insigwait_mask = tls ? sigismember (&tls->sigwait_mask, sig) : false; + bool special_case = ISSTATE (myself, PID_STOPPED) || main_vfork->pid; + bool masked = sigismember (&mask, sig); if (sig != SIGKILL && sig != SIGSTOP - && (sigismember (&mask, sig) - || (tls - && (insigwait_mask || sigismember (&tls->sigmask, sig))) - || main_vfork->pid - || ISSTATE (myself, PID_STOPPED))) + && (special_case || main_vfork->pid || masked || insigwait_mask + || (tls && sigismember (&tls->sigmask, sig)))) { sigproc_printf ("signal %d blocked", sig); - if (insigwait_mask || (tls = _threadinfo::find_tls (sig)) != NULL) + if ((!special_case && !masked) + && (insigwait_mask || (tls = _threadinfo::find_tls (sig)) != NULL)) goto thread_specific; rc = -1; goto done; @@ -1045,12 +1023,6 @@ signal_exit (int rc) (void) SetThreadPriority (hMainThread, THREAD_PRIORITY_IDLE); (void) SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL); - /* Unlock any main thread mutos since we're executing with prejudice. */ - muto *m; - for (m = muto_start.next; m != NULL; m = m->next) - if (m->unstable () || m->owner () == cygthread::main_thread_id) - m->reset (); - user_data->resourcelocks->Delete (); user_data->resourcelocks->Init (); @@ -1114,6 +1086,7 @@ call_signal_handler_now () sa_flags = _my_tls.sa_flags; int sig = _my_tls.sig; void (*sigfunc) (int) = _my_tls.func; + (void) _my_tls.pop (); #ifdef DEBUGGING if (_my_tls.stackptr > (_my_tls.stack + 1)) diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index 07b58b281..b637d2fbd 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -135,16 +135,6 @@ cygwin_internal (cygwin_getinfo_types t, ...) { va_list arg; va_start (arg, t); - if (t != CW_USER_DATA) - { - wincap.init (); - if (!myself) - { - memory_init (); - malloc_init (); - set_myself (1); - } - } switch (t) { diff --git a/winsup/cygwin/external.sgml b/winsup/cygwin/external.sgml index 88d67252f..270eede4d 100644 --- a/winsup/cygwin/external.sgml +++ b/winsup/cygwin/external.sgml @@ -3,12 +3,10 @@ cygwin_internal - extern "C" DWORD cygwin_internal cygwin_getinfo_types t ... - This function gives you access to various internal data and functions. diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index b4ff074fa..407a47ddd 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -167,8 +167,8 @@ sync_with_child (PROCESS_INFORMATION &pi, HANDLE subproc_ready, */ if (errcode != STATUS_CONTROL_C_EXIT) { - system_printf ("child %d(%p) died before initialization with status code %p", - pi.dwProcessId, pi.hProcess, errcode); + system_printf ("child %u(%p) died before initialization with status code %p", + cygwin_pid (pi.dwProcessId), pi.hProcess, errcode); system_printf ("*** child state %s", s); #ifdef DEBUGGING abort (); @@ -263,7 +263,7 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls) if (fork_info->stacksize) { _main_tls = &_my_tls; - _main_tls->init_thread (NULL); + _main_tls->init_thread (NULL, NULL); _main_tls->local_clib = *_impure_ptr; _impure_ptr = &_main_tls->local_clib; } @@ -721,6 +721,7 @@ vfork () vf->pgid = myself->pgid; cygheap->ctty_on_hold = cygheap->ctty; vf->open_fhs = cygheap->open_fhs; + debug_printf ("cygheap->ctty_on_hold %p, cygheap->open_fhs %d", cygheap->ctty_on_hold, cygheap->open_fhs); int res = cygheap->fdtab.vfork_child_dup () ? 0 : -1; debug_printf ("%d = vfork()", res); call_signal_handler_now (); // FIXME: racy diff --git a/winsup/cygwin/heap.cc b/winsup/cygwin/heap.cc index 95d9b17bc..af5ec2fe5 100644 --- a/winsup/cygwin/heap.cc +++ b/winsup/cygwin/heap.cc @@ -31,7 +31,6 @@ extern "C" size_t getpagesize (); #define MINHEAP_SIZE (4 * 1024 * 1024) /* Initialize the heap at process start up. */ - void heap_init () { @@ -64,12 +63,11 @@ heap_init () /* total size commited in parent */ DWORD allocsize = (char *) cygheap->user_heap.top - (char *) cygheap->user_heap.base; - /* round up by chunk size */ - DWORD reserve_size = chunk * ((allocsize + (chunk - 1)) / chunk); /* Loop until we've managed to reserve an adequate amount of memory. */ char *p; - for (;;) + DWORD reserve_size = chunk * ((allocsize + (chunk - 1)) / chunk); + while (1) { p = (char *) VirtualAlloc (cygheap->user_heap.base, reserve_size, MEM_RESERVE, PAGE_READWRITE); @@ -78,8 +76,13 @@ heap_init () if ((reserve_size -= page_const) <= allocsize) break; } + if (!p) + api_fatal ("couldn't allocate cygwin heap, %E, base %p, top %p, " + "reserve_size %d, allocsize %d, page_const %d", + cygheap->user_heap.base, cygheap->user_heap.top, + reserve_size, allocsize, page_const); if (p != cygheap->user_heap.base) - api_fatal ("heap allocated but not at %p", cygheap->user_heap.base); + api_fatal ("heap allocated at wrong address %p (mapped) != %p (expected)", p, cygheap->user_heap.base); if (!VirtualAlloc (cygheap->user_heap.base, allocsize, MEM_COMMIT, PAGE_READWRITE)) api_fatal ("MEM_COMMIT failed, %E"); } @@ -87,7 +90,7 @@ heap_init () debug_printf ("heap base %p, heap top %p", cygheap->user_heap.base, cygheap->user_heap.top); page_const--; - malloc_init (); + // malloc_init (); } #define pround(n) (((size_t)(n) + page_const) & ~page_const) diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc index f6a29f2d6..a85a8a270 100644 --- a/winsup/cygwin/init.cc +++ b/winsup/cygwin/init.cc @@ -16,51 +16,95 @@ details. */ #include "cygtls.h" int NO_COPY dynamically_loaded; +static char *search_for = (char *) cygthread::stub; +static unsigned threadfunc_ix __attribute__((section ("cygwin_dll_common"), shared)) = 0; +DWORD tls_func; + +HANDLE sync_startup; + +#define OLDFUNC_OFFSET -1 static void WINAPI threadfunc_fe (VOID *arg) { - _threadinfo::call ((DWORD (*) (void *, void *)) (((char **) _tlsbase)[-1]), arg); + _threadinfo::call ((DWORD (*) (void *, void *)) (((char **) _tlsbase)[OLDFUNC_OFFSET]), arg); + // void *threadfunc = (void *) TlsGetValue (tls_func); + // TlsFree (tls_func); + // _threadinfo::call ((DWORD (*) (void *, void *)) (threadfunc), arg); +} + +static DWORD WINAPI +calibration_thread (VOID *arg) +{ + ExitThread (0); } static void munge_threadfunc (HANDLE cygwin_hmodule) { - char **ebp = (char **) __builtin_frame_address (0); - static unsigned threadfunc_ix; + char **ebp = (char **) __builtin_frame_address (0); if (!threadfunc_ix) { for (char **peb = ebp; peb < (char **) _tlsbase; peb++) - if (*peb == (char *) cygthread::stub) + if (*peb == search_for) { threadfunc_ix = peb - ebp; goto foundit; } +#ifdef DEBUGGING + system_printf ("non-fatal warning: unknown thread! search_for %p, cygthread::stub %p, calibration_thread %p, possible func offset %p", + search_for, cygthread::stub, calibration_thread, ebp[137]); +#endif + try_to_debug (); return; } foundit: char *threadfunc = ebp[threadfunc_ix]; - ebp[threadfunc_ix] = (char *) threadfunc_fe; - ((char **) _tlsbase)[-1] = threadfunc; + if (threadfunc == (char *) calibration_thread) + /* no need for the overhead */; + else + { + ebp[threadfunc_ix] = (char *) threadfunc_fe; + ((char **) _tlsbase)[OLDFUNC_OFFSET] = threadfunc; + // TlsSetValue (tls_func, (void *) threadfunc); + } } +void +prime_threads () +{ + // tls_func = TlsAlloc (); + if (!threadfunc_ix) + { + DWORD id; + search_for = (char *) calibration_thread; + sync_startup = CreateThread (NULL, 0, calibration_thread, 0, 0, &id); + } +} + +extern void __stdcall dll_crt0_0 (); + extern "C" int WINAPI dll_entry (HANDLE h, DWORD reason, void *static_load) { switch (reason) { case DLL_PROCESS_ATTACH: + prime_threads (); dynamically_loaded = (static_load == NULL); // __cygwin_user_data.impure_ptr = &_my_tls.local_clib; - _my_tls.stackptr = NULL; + dll_crt0_0 (); + // small_printf ("%u, %p, %p\n", cygwin_pid (GetCurrentProcessId ()), _tlstop, _tlsbase); break; case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: munge_threadfunc (h); + // small_printf ("%u, %p, %p\n", cygwin_pid (GetCurrentProcessId ()), _tlstop, _tlsbase); break; case DLL_THREAD_DETACH: + _my_tls.remove (0); break; } return 1; diff --git a/winsup/cygwin/malloc_wrapper.cc b/winsup/cygwin/malloc_wrapper.cc index 5798cf417..7bcd181c5 100644 --- a/winsup/cygwin/malloc_wrapper.cc +++ b/winsup/cygwin/malloc_wrapper.cc @@ -316,6 +316,7 @@ 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 diff --git a/winsup/cygwin/path.sgml b/winsup/cygwin/path.sgml index 6638e92e5..6030c8f78 100644 --- a/winsup/cygwin/path.sgml +++ b/winsup/cygwin/path.sgml @@ -2,12 +2,10 @@ cygwin_posix_to_win32_path_list - extern "C" void cygwin_posix_to_win32_path_list const char *posix char *win32 - Given a POSIX path-style string (i.e. /foo:/bar) convert it to @@ -41,12 +39,10 @@ cygwin_posix_to_win32_path_list_buf_size cygwin_win32_to_posix_path_list - extern "C" void cygwin_win32_to_posix_path_list const char *win32 char *posix - Given a Win32 path-style string (i.e. d:\;e:\bar) convert it to @@ -62,11 +58,9 @@ cygwin_win32_to_posix_path_list_buf_size cygwin_posix_to_win32_path_list_buf_size - extern "C" int cygwin_posix_to_win32_path_list_buf_size const char *path_list - Returns the number of bytes needed to hold the result of calling @@ -79,11 +73,9 @@ cygwin_posix_to_win32_path_list. cygwin_win32_to_posix_path_list_buf_size - extern "C" int cygwin_win32_to_posix_path_list_buf_size const char *path_list - Tells you how many bytes are needed for the results of . cygwin_conv_to_posix_path - extern "C" void cygwin_conv_to_posix_path const char *path char *posix_path - Converts a Win32 path to a POSIX path. If @@ -117,12 +107,10 @@ size; use MAX_PATH if needed. cygwin_conv_to_win32_path - extern "C" void cygwin_conv_to_win32_path const char *path char *win32_path - Converts a POSIX path to a Win32 path. If @@ -137,12 +125,10 @@ size; use MAX_PATH if needed. cygwin_conv_to_full_posix_path - extern "C" void cygwin_conv_to_full_posix_path const char *path char *posix_path - Converts a Win32 path to a POSIX path. If @@ -158,12 +144,10 @@ buffer of sufficient size; use MAX_PATH if needed. cygwin_conv_to_full_win32_path - extern "C" void cygwin_conv_to_full_win32_path const char *path char *win32_path - Converts a POSIX path to a Win32 path. If @@ -179,11 +163,9 @@ buffer of sufficient size; use MAX_PATH if needed. cygwin_posix_path_list_p - extern "C" int posix_path_list_p const char *path - This function tells you if the supplied @@ -200,14 +182,12 @@ parameter. cygwin_split_path - extern "C" void cygwin_split_path const char * path char * dir char * file - Split a path into the directory and the file portions. Both diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 2eca86a33..834fa8574 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -610,12 +610,10 @@ pinfo::release () cygwin_winpid_to_pid - extern "C" pid_t cygwin_winpid_to_pid int winpid - Given a windows pid, converts to the corresponding Cygwin diff --git a/winsup/cygwin/select.h b/winsup/cygwin/select.h index 30b59964f..d38e19cee 100644 --- a/winsup/cygwin/select.h +++ b/winsup/cygwin/select.h @@ -1,6 +1,6 @@ /* select.h - Copyright 1998, 1999, 2000, 2001 Red Hat, Inc. + Copyright 1998, 1999, 2000, 2001, 2004 Red Hat, Inc. This file is part of Cygwin. @@ -52,5 +52,4 @@ extern "C" int PASCAL win32_select(int, fd_set*, fd_set*, fd_set*, const struct * type coercion need to appease confused prototypes */ #define WINSOCK_SELECT(nfd, rd, wr, ex, timeo) \ - win32_select (nfd, (fd_set *)rd, (fd_set *)wr, (fd_set *)ex, timeo) - + win32_select (nfd, (fd_set *) rd, (fd_set *) wr, (fd_set *) ex, timeo) diff --git a/winsup/cygwin/shared.sgml b/winsup/cygwin/shared.sgml index f06f065fa..f43d654e2 100644 --- a/winsup/cygwin/shared.sgml +++ b/winsup/cygwin/shared.sgml @@ -3,11 +3,9 @@ cygwin_getshared - shared_info * cygwin_getshared - Returns a pointer to an internal Cygwin memory structure diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 25bce8468..e143a8239 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -1,6 +1,6 @@ /* sigproc.cc: inter/intra signal and sub process handler - Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. + Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. Written by Christopher Faylor @@ -32,6 +32,7 @@ details. */ #include "cygtls.h" #include "sigproc.h" #include "perthread.h" +#include "exceptions.h" /* * Convenience defines @@ -1105,12 +1106,17 @@ wait_sig (VOID *self) SetEvent (wait_sig_inited); sigtid = GetCurrentThreadId (); + exception_list el; + _my_tls.init_threadlist_exceptions (&el); + for (;;) { DWORD nb; sigpacket pack; if (!ReadFile (readsig, &pack, sizeof (pack), &nb, NULL)) break; + if (myself->sendsig == INVALID_HANDLE_VALUE) + break; if (nb != sizeof (pack)) { diff --git a/winsup/cygwin/stackdump.sgml b/winsup/cygwin/stackdump.sgml index 5c209541b..bff76bffd 100644 --- a/winsup/cygwin/stackdump.sgml +++ b/winsup/cygwin/stackdump.sgml @@ -2,11 +2,9 @@ cygwin_stackdump - extern "C" void cygwin_stackdump - Outputs a stackdump to stderr from the called location. diff --git a/winsup/cygwin/sync.cc b/winsup/cygwin/sync.cc index b6dec83fa..dbc26304b 100644 --- a/winsup/cygwin/sync.cc +++ b/winsup/cygwin/sync.cc @@ -23,10 +23,10 @@ details. */ #include "sync.h" #include "security.h" -muto NO_COPY muto_start; - #undef WaitForSingleObject +DWORD NO_COPY muto::exiting_thread; + /* Constructor */ muto * muto::init (const char *s) @@ -40,8 +40,6 @@ muto::init (const char *s) return NULL; } name = s; - next = muto_start.next; - muto_start.next = this; return this; } @@ -71,6 +69,8 @@ int muto::acquire (DWORD ms) { DWORD this_tid = GetCurrentThreadId (); + if (exiting_thread) + return this_tid == exiting_thread; if (tid != this_tid) { @@ -113,6 +113,8 @@ int muto::release () { DWORD this_tid = GetCurrentThreadId (); + if (exiting_thread) + return this_tid == exiting_thread; if (tid != this_tid || !visits) { @@ -135,6 +137,12 @@ muto::release () return 1; /* success. */ } +bool +muto::acquired () +{ + return tid == GetCurrentThreadId (); +} + /* Call only when we're exiting. This is not thread safe. */ void muto::reset () diff --git a/winsup/cygwin/sync.h b/winsup/cygwin/sync.h index 9cd50c3ac..3ae09373f 100644 --- a/winsup/cygwin/sync.h +++ b/winsup/cygwin/sync.h @@ -10,17 +10,20 @@ This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ +#ifndef _SYNC_H +#define _SYNC_H /* FIXME: Note that currently this class cannot be allocated via `new' since there are issues with malloc and fork. */ class muto { + static DWORD exiting_thread; LONG sync; /* Used to serialize access to this class. */ LONG visits; /* Count of number of times a thread has called acquire. */ LONG waiters; /* Number of threads waiting for lock. */ HANDLE bruteforce; /* event handle used to control waiting for lock. */ DWORD tid; /* Thread Id of lock owner. */ public: - class muto *next; + // class muto *next; const char *name; /* The real constructor. */ @@ -37,6 +40,8 @@ public: DWORD owner () {return tid;} int unstable () {return !tid && (sync || waiters >= 0);} void reset () __attribute__ ((regparm (1))); + bool acquired (); + static void set_exiting_thread () {exiting_thread = GetCurrentThreadId ();} }; extern muto muto_start; @@ -44,6 +49,14 @@ extern muto muto_start; /* Use a statically allocated buffer as the storage for a muto */ #define new_muto(__name) \ ({ \ - static muto __name##_storage __attribute__((nocommon)) __attribute__((section(".data_cygwin_nocopy"))); \ + static muto __name##_storage __attribute__((nocommon)) __attribute__((section(".data_cygwin_nocopy1"))); \ __name = __name##_storage.init (#__name); \ }) + +/* Use a statically allocated buffer as the storage for a muto */ +#define new_muto1(__name, __storage) \ +({ \ + static muto __storage __attribute__((nocommon)) __attribute__((section(".data_cygwin_nocopy1"))); \ + __name = __storage.init (#__name); \ +}) +#endif /*_SYNC_H*/ diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 47d6b10de..5abe0caf9 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -87,7 +87,7 @@ static int __stdcall stat_worker (const char *name, struct __stat64 *buf, void __stdcall close_all_files (void) { - SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "close_all_files"); + cygheap->fdtab.lock (); fhandler_base *fh; for (int i = 0; i < (int) cygheap->fdtab.size; i++) @@ -101,13 +101,9 @@ close_all_files (void) } if (cygheap->ctty) - { - debug_printf ("closing ctty"); - cygheap->ctty->close (); - cygheap->ctty = NULL; - } + cygheap->close_ctty (); - ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "close_all_files"); + cygheap->fdtab.unlock (); user_shared->delqueue.process_queue (); } @@ -332,10 +328,7 @@ setsid (void) syscall_printf ("sid %d, pgid %d, ctty %d, open_fhs %d", myself->sid, myself->pgid, myself->ctty, cygheap->open_fhs); if (cygheap->ctty) - { - cygheap->ctty->close (); - cygheap->ctty = NULL; - } + cygheap->close_ctty (); return myself->sid; } diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index fe460a19b..ae03dc626 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -297,7 +297,7 @@ pthread::exit (void *value_ptr) ::exit (0); else { - _my_tls.remove (); + _my_tls.remove (INFINITE); ExitThread (0); } } @@ -1783,9 +1783,6 @@ pthread::thread_init_wrapper (void *arg) pthread *thread = (pthread *) arg; _my_tls.tid = thread; - exception_list cygwin_except_entry; - init_exceptions (&cygwin_except_entry); /* Initialize SIGSEGV handling, etc. */ - thread->mutex.lock (); // if thread is detached force cleanup on exit diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index ed79b8deb..0e9779a62 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -14,10 +14,7 @@ details. */ #ifndef _CYGNUS_THREADS_ #define _CYGNUS_THREADS_ -#define LOCK_FD_LIST 1 -#define LOCK_MEMORY_LIST 2 -#define LOCK_MMAP_LIST 3 -#define LOCK_DLL_LIST 4 +#define LOCK_MMAP_LIST 1 #define WRITE_LOCK 1 #define READ_LOCK 2 diff --git a/winsup/cygwin/tlsoffsets.h b/winsup/cygwin/tlsoffsets.h index 191fe3744..6aeea68d5 100644 --- a/winsup/cygwin/tlsoffsets.h +++ b/winsup/cygwin/tlsoffsets.h @@ -1,44 +1,46 @@ //;# autogenerated: Do not edit. -//; $tls::func = -7148; -//; $tls::saved_errno = -7144; -//; $tls::sa_flags = -7140; -//; $tls::oldmask = -7136; -//; $tls::newmask = -7132; -//; $tls::event = -7128; -//; $tls::errno_addr = -7124; -//; $tls::initialized = -7120; -//; $tls::sigmask = -7116; -//; $tls::sigwait_mask = -7112; -//; $tls::sigwait_info = -7108; -//; $tls::infodata = -7104; -//; $tls::tid = -6580; -//; $tls::local_clib = -6576; -//; $tls::locals = -5648; -//; $tls::prev = -4112; -//; $tls::next = -4108; -//; $tls::stackptr = -4104; -//; $tls::sig = -4100; -//; $tls::stack = -4096; +//; $tls::func = -4076; +//; $tls::saved_errno = -4072; +//; $tls::sa_flags = -4068; +//; $tls::oldmask = -4064; +//; $tls::newmask = -4060; +//; $tls::event = -4056; +//; $tls::errno_addr = -4052; +//; $tls::initialized = -4048; +//; $tls::sigmask = -4044; +//; $tls::sigwait_mask = -4040; +//; $tls::sigwait_info = -4036; +//; $tls::infodata = -4032; +//; $tls::tid = -3508; +//; $tls::local_clib = -3504; +//; $tls::locals = -2576; +//; $tls::prev = -1040; +//; $tls::next = -1036; +//; $tls::stackptr = -1032; +//; $tls::sig = -1028; +//; $tls::stack = -1024; +//; $tls::padding = 0; //; __DATA__ -#define tls_func (-7148) -#define tls_saved_errno (-7144) -#define tls_sa_flags (-7140) -#define tls_oldmask (-7136) -#define tls_newmask (-7132) -#define tls_event (-7128) -#define tls_errno_addr (-7124) -#define tls_initialized (-7120) -#define tls_sigmask (-7116) -#define tls_sigwait_mask (-7112) -#define tls_sigwait_info (-7108) -#define tls_infodata (-7104) -#define tls_tid (-6580) -#define tls_local_clib (-6576) -#define tls_locals (-5648) -#define tls_prev (-4112) -#define tls_next (-4108) -#define tls_stackptr (-4104) -#define tls_sig (-4100) -#define tls_stack (-4096) +#define tls_func (-4076) +#define tls_saved_errno (-4072) +#define tls_sa_flags (-4068) +#define tls_oldmask (-4064) +#define tls_newmask (-4060) +#define tls_event (-4056) +#define tls_errno_addr (-4052) +#define tls_initialized (-4048) +#define tls_sigmask (-4044) +#define tls_sigwait_mask (-4040) +#define tls_sigwait_info (-4036) +#define tls_infodata (-4032) +#define tls_tid (-3508) +#define tls_local_clib (-3504) +#define tls_locals (-2576) +#define tls_prev (-1040) +#define tls_next (-1036) +#define tls_stackptr (-1032) +#define tls_sig (-1028) +#define tls_stack (-1024) +#define tls_padding (0) diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 2d60fcd52..6c2e58faf 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -8,6 +8,12 @@ This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ +#ifdef DEBUGIT +#define spf(a, b, c) small_printf (a, b, c) +#else +#define spf(a, b, c) do {} while (0) +#endif + #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -150,11 +156,11 @@ extern HANDLE title_mutex; }) /* Convert a signal to a signal mask */ -#define SIGTOMASK(sig) (1<<((sig) - signal_shift_subtract)) +#define SIGTOMASK(sig) (1 << ((sig) - signal_shift_subtract)) extern unsigned int signal_shift_subtract; #ifdef NEW_MACRO_VARARGS -# define api_fatal(...) __api_fatal ("%P: *** " __VA_ARGS__) +# define api_fatal(...) __api_fatal (__VA_ARGS__) #else # define api_fatal(fmt, args...) __api_fatal ("%P: *** " fmt,## args) #endif