diff options
author | Corinna Vinschen <vinschen@redhat.com> | 2008-03-02 10:40:38 +0000 |
---|---|---|
committer | Corinna Vinschen <vinschen@redhat.com> | 2008-03-02 10:40:38 +0000 |
commit | 10ea147233bf6f64ecafc8fb61b116b3f38e7286 (patch) | |
tree | bf5b9b4bf75040bb232ac3c385c658dd084aa5a1 | |
parent | 341facafabf512e96ff864779ff6c5e2ef2e4f6d (diff) | |
download | gdb-10ea147233bf6f64ecafc8fb61b116b3f38e7286.tar.gz |
2008-03-01 Christopher Faylor <me+cygwin@cgf.cx>
* cygtls.h (_cygtls::handle_threadlist_exception): Eliminate.
(_cygtls::init_threadlist_exceptions): Ditto.
* cygtls.cc (_cygtls::handle_threadlist_exception): Eliminate.
(_cygtls::init_threadlist_exceptions): Ditto.
(_cygtls::find_tls): Use myfault handling to deal with errors caused by
nonexistent threads.
* sigproc.cc (wait_sig): Eliminate call to init_threadlist_exceptions.
2008-03-01 Christopher Faylor <me+cygwin@cgf.cx>
* cygtls.cc (_cygtls::init_exception_handler): Just return.
2008-03-01 Corinna Vinschen <corinna@vinschen.de>
* exceptions.cc (_cygtls::handle_exceptions): Only call rtl_unwind when
exiting. Just return, don't set thread context.
* gendef (_setjmp): Store %fs:0 in jmp_buf.
(_sjfault): Ditto.
(_ljfault): Restore %fs:0 from jmp_buf.
(_longjmp): Ditto.
-rw-r--r-- | winsup/cygwin/ChangeLog | 23 | ||||
-rw-r--r-- | winsup/cygwin/cygtls.cc | 51 | ||||
-rw-r--r-- | winsup/cygwin/cygtls.h | 263 | ||||
-rw-r--r-- | winsup/cygwin/exceptions.cc | 18 | ||||
-rwxr-xr-x | winsup/cygwin/gendef | 12 | ||||
-rw-r--r-- | winsup/cygwin/sigproc.cc | 1 |
6 files changed, 308 insertions, 60 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index ef73223a5c1..b02bab1814d 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,26 @@ +2008-03-01 Christopher Faylor <me+cygwin@cgf.cx> + + * cygtls.h (_cygtls::handle_threadlist_exception): Eliminate. + (_cygtls::init_threadlist_exceptions): Ditto. + * cygtls.cc (_cygtls::handle_threadlist_exception): Eliminate. + (_cygtls::init_threadlist_exceptions): Ditto. + (_cygtls::find_tls): Use myfault handling to deal with errors caused by + nonexistent threads. + * sigproc.cc (wait_sig): Eliminate call to init_threadlist_exceptions. + +2008-03-01 Christopher Faylor <me+cygwin@cgf.cx> + + * cygtls.cc (_cygtls::init_exception_handler): Just return. + +2008-03-01 Corinna Vinschen <corinna@vinschen.de> + + * exceptions.cc (_cygtls::handle_exceptions): Only call rtl_unwind when + exiting. Just return, don't set thread context. + * gendef (_setjmp): Store %fs:0 in jmp_buf. + (_sjfault): Ditto. + (_ljfault): Restore %fs:0 from jmp_buf. + (_longjmp): Ditto. + 2008-02-29 Corinna Vinschen <corinna@vinschen.de> * fhandler_disk_file.cc (fhandler_disk_file::fchmod): Call close_fs diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index c2d7c2ed72e..88fd49753da 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -196,23 +196,28 @@ _cygtls::push (__stack_t addr) *stackptr++ = (__stack_t) addr; } -#define BAD_IX ((size_t) -1) -static size_t NO_COPY threadlist_ix = BAD_IX; _cygtls * _cygtls::find_tls (int sig) { + static int NO_COPY threadlist_ix; + debug_printf ("sig %d\n", sig); sentry here (INFINITE); - __asm__ volatile (".equ _threadlist_exception_return,."); + _cygtls *res = NULL; - for (threadlist_ix = 0; threadlist_ix < nthreads; threadlist_ix++) + threadlist_ix = -1; + + myfault efault; + if (efault.faulted ()) + cygheap->threadlist[threadlist_ix]->remove (INFINITE); + + while (++threadlist_ix < (int) nthreads) if (sigismember (&(cygheap->threadlist[threadlist_ix]->sigwait_mask), sig)) { res = cygheap->threadlist[threadlist_ix]; break; } - threadlist_ix = BAD_IX; return res; } @@ -222,36 +227,6 @@ _cygtls::set_siginfo (sigpacket *pack) infodata = pack->si; } -extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD) __attribute__ ((noreturn)); -int -_cygtls::handle_threadlist_exception (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *c, void *) -{ - if (e->ExceptionCode != STATUS_ACCESS_VIOLATION) - { - system_printf ("unhandled exception %p at %p", e->ExceptionCode, c->Eip); - return 1; - } - - sentry here; - if (threadlist_ix == BAD_IX) - { - api_fatal ("called with threadlist_ix %d", BAD_IX); - return 1; - } - - if (!here.acquired ()) - { - system_printf ("couldn't aquire muto"); - return 1; - } - - extern void *threadlist_exception_return; - cygheap->threadlist[threadlist_ix]->remove (INFINITE); - threadlist_ix = 0; - RtlUnwind (frame, threadlist_exception_return, e, 0); - /* Never returns */ -} - /* Set up the exception handler for the current thread. The x86 uses segment register fs, offset 0 to point to the current exception handler. */ @@ -275,9 +250,3 @@ _cygtls::init_exception_handler (exception_handler *eh) el.prev = _except_list; _except_list = ⪙ } - -void -_cygtls::init_threadlist_exceptions () -{ - init_exception_handler (handle_threadlist_exception); -} diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h new file mode 100644 index 00000000000..e60eb359491 --- /dev/null +++ b/winsup/cygwin/cygtls.h @@ -0,0 +1,263 @@ +/* cygtls.h + + Copyright 2003, 2004, 2005 Red Hat, Inc. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifndef _CYGTLS_H +#define _CYGTLS_H + +#include <signal.h> +#include <pwd.h> +#include <grp.h> +#include <sys/time.h> +#define _NOMNTENT_FUNCS +#include <mntent.h> +#undef _NOMNTENT_FUNCS +#include <setjmp.h> +#include <exceptions.h> +#ifndef _WINSOCK_H +#include <netinet/in.h> +typedef unsigned int SOCKET; +#endif + +#define CYGTLS_INITIALIZED 0xc763173f + +#ifndef CYG_MAX_PATH +# define CYG_MAX_PATH 260 +#endif + +#ifndef UNLEN +# define UNLEN 256 +#endif + +#define TLS_STACK_SIZE 256 + +#include "cygthread.h" + +#pragma pack(push,4) +struct _local_storage +{ + /* + Needed for the group functions + */ + struct __group16 grp; + char *namearray[2]; + int grp_pos; + + /* console.cc */ + unsigned rarg; + + /* dlfcn.cc */ + int dl_error; + char dl_buffer[256]; + + /* passwd.cc */ + struct passwd res; + char pass[_PASSWORD_LEN]; + int pw_pos; + + /* path.cc */ + struct mntent mntbuf; + int iteration; + unsigned available_drives; + char mnt_type[80]; + char mnt_opts[80]; + char mnt_fsname[CYG_MAX_PATH]; + char mnt_dir[CYG_MAX_PATH]; + + /* select.cc */ + SOCKET exitsock; + struct sockaddr_in exitsock_sin; + + /* strerror */ + char strerror_buf[sizeof ("Unknown error 4294967295")]; + + /* sysloc.cc */ + char *process_ident; // note: malloced + int process_logopt; + int process_facility; + int process_logmask; + + /* times.cc */ + char timezone_buf[20]; + struct tm _localtime_buf; + + /* uinfo.cc */ + char username[UNLEN + 1]; + + /* net.cc */ + char *ntoa_buf; // note: malloced + struct protoent *protoent_buf; // note: malloced + struct servent *servent_buf; // note: malloced + struct hostent *hostent_buf; // note: malloced + char signamebuf[sizeof ("Unknown signal 4294967295 ")]; + + /* cygthread.cc */ + char unknown_thread_name[30]; + + /* syscalls.cc */ + int setmode_file; + int setmode_mode; +}; + +typedef struct struct_waitq +{ + int pid; + int options; + int status; + HANDLE ev; + void *rusage; /* pointer to potential rusage */ + struct struct_waitq *next; + HANDLE thread_ev; +} waitq; + +typedef struct +{ + void *_myfault; + int _myfault_errno; +} san; + +/* Changes to the below structure may require acompanying changes to the very + simple parser in the perl script 'gentls_offsets' (<<-- start parsing here). + The union in this structure is used to force alignment between the version + of the compiler used to generate tlsoffsets.h and the cygwin cross compiler. +*/ + +/*gentls_offsets*/ +#include "cygerrno.h" + +extern "C" int __sjfault (jmp_buf); +extern "C" int __ljfault (jmp_buf, int); + +/*gentls_offsets*/ + +typedef __uint32_t __stack_t; +struct _cygtls +{ + void (*func) /*gentls_offsets*/(int)/*gentls_offsets*/; + exception_list el; + int saved_errno; + int sa_flags; + sigset_t oldmask; + sigset_t deltamask; + HANDLE event; + int *errno_addr; + sigset_t sigmask; + sigset_t sigwait_mask; + siginfo_t *sigwait_info; + struct ucontext thread_context; + DWORD thread_id; + unsigned threadkill; + siginfo_t infodata; + struct pthread *tid; + union + { + struct _reent local_clib; + char __dontuse[8 * ((sizeof(struct _reent) + 4) / 8)]; + }; + struct _local_storage locals; + class cygthread *_ctinfo; + san andreas; + waitq wq; + struct _cygtls *prev, *next; + int sig; + unsigned incyg; + unsigned spinning; + unsigned stacklock; + __stack_t *stackptr; + __stack_t stack[TLS_STACK_SIZE]; + unsigned initialized; + + /*gentls_offsets*/ + static CRITICAL_SECTION protect_linked_list; + static void init (); + void init_thread (void *, DWORD (*) (void *, void *)); + static void call (DWORD (*) (void *, void *), void *); + void call2 (DWORD (*) (void *, void *), void *, void *) __attribute__ ((regparm (3))); + static struct _cygtls *find_tls (int sig); + void remove (DWORD); + void push (__stack_t) __attribute__ ((regparm (2))); + __stack_t pop () __attribute__ ((regparm (1))); + __stack_t retaddr () {return stackptr[-1];} + bool isinitialized () const + { + volatile char here; + return ((char *) this > &here) && initialized == CYGTLS_INITIALIZED; + } + bool interrupt_now (CONTEXT *, int, void *, struct sigaction&) + __attribute__((regparm(3))); + void __stdcall interrupt_setup (int sig, void *handler, + struct sigaction& siga) + __attribute__((regparm(3))); + + /* exception handling */ + static int handle_exceptions (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void *); + void init_exception_handler (int (*) (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void*)); + void signal_exit (int) __attribute__ ((noreturn, regparm(2))); + void copy_context (CONTEXT *) __attribute__ ((regparm(2))); + void signal_debugger (int) __attribute__ ((regparm(2))); + +#ifdef _THREAD_H + operator HANDLE () const {return tid->win32_obj_id;} +#endif + void set_siginfo (struct sigpacket *) __attribute__ ((regparm (3))); + void set_threadkill () {threadkill = true;} + void reset_threadkill () {threadkill = false;} + int call_signal_handler () __attribute__ ((regparm (1))); + void remove_wq (DWORD) __attribute__ ((regparm (1))); + void fixup_after_fork () __attribute__ ((regparm (1))); + void lock () __attribute__ ((regparm (1))); + void unlock () __attribute__ ((regparm (1))); + bool locked () __attribute__ ((regparm (1))); + void*& fault_guarded () {return andreas._myfault;} + void return_from_fault () + { + if (andreas._myfault_errno) + set_errno (andreas._myfault_errno); + __ljfault ((int *) andreas._myfault, 1); + } + int setup_fault (jmp_buf j, san& old_j, int myerrno) __attribute__ ((always_inline)) + { + old_j._myfault = andreas._myfault; + old_j._myfault_errno = andreas._myfault_errno; + andreas._myfault = (void *) j; + andreas._myfault_errno = myerrno; + return __sjfault (j); + } + void reset_fault (san& old_j) __attribute__ ((always_inline)) + { + andreas._myfault = old_j._myfault; + andreas._myfault_errno = old_j._myfault_errno; + } + /*gentls_offsets*/ +}; +#pragma pack(pop) + +const int CYGTLS_PADSIZE = 12700; /* FIXME: Find some way to autogenerate + this value */ +/*gentls_offsets*/ + +extern char *_tlsbase __asm__ ("%fs:4"); +extern char *_tlstop __asm__ ("%fs:8"); +#define _my_tls (*((_cygtls *) (_tlsbase - CYGTLS_PADSIZE))) +extern _cygtls *_main_tls; +extern _cygtls *_sig_tls; + +class myfault +{ + jmp_buf buf; + san sebastian; +public: + ~myfault () __attribute__ ((always_inline)) { _my_tls.reset_fault (sebastian); } + inline int faulted (int myerrno = 0) __attribute__ ((always_inline)) + { + return _my_tls.setup_fault (buf, sebastian, myerrno); + } +}; + +#define __getreent() (&_my_tls.local_clib) + +#endif /*_CYGTLS_H*/ /*gentls_offsets*/ diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 9dfe6f3d92c..ce98d2154e2 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -583,8 +583,6 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT return 1; } - rtl_unwind (frame, e); - debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp); debug_printf ("In cygwin_except_handler sig %d at %p", si.si_signo, in->Eip); @@ -634,6 +632,7 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT goto out; } + rtl_unwind (frame, e); open_stackdumpfile (); exception (e, in); stackdump ((DWORD) ebp, 0, 1); @@ -664,21 +663,8 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT sig_send (NULL, si, &me); // Signal myself me.incyg--; e->ExceptionFlags = 0; - /* The OS adds an exception list frame to the stack. It expects to be - able to remove this entry after the exception handler returned. - However, when unwinding to our frame, our frame becomes the uppermost - frame on the stack (%fs:0 points to frame). This way, our frame - is removed from the exception stack and just disappears. So, we can't - just return here or things will be screwed up by the helpful function - in (presumably) ntdll.dll. - - So, instead, we will do the equivalent of a longjmp here and return - to the caller without visiting any of the helpful code installed prior - to this function. This should work ok, since a longjmp() out of here has - to work if linux signal semantics are to be maintained. */ out: - SetThreadContext (GetCurrentThread (), in); - return 0; /* Never actually returns. This is just to keep gcc happy. */ + return 0; } /* Utilities to call a user supplied exception handler. */ diff --git a/winsup/cygwin/gendef b/winsup/cygwin/gendef index 0d7df4b090c..28d4b3125fd 100755 --- a/winsup/cygwin/gendef +++ b/winsup/cygwin/gendef @@ -332,12 +332,14 @@ _setjmp: movw %ax,40(%edi) movw %ss,%ax movw %ax,42(%edi) + movl %fs:0,%eax + movl %eax,44(%edi) pushl %ebx call stabilize_sig_stack movl $tls::stackptr(%ebx),%eax # save stack pointer contents decl $tls::stacklock(%ebx) popl %ebx - movl %eax,44(%edi) + movl %eax,48(%edi) popl %edi movl \$0,%eax leave @@ -371,6 +373,8 @@ ___sjfault: movw %ax,40(%edi) movw %ss,%ax movw %ax,42(%edi) + movl %fs:0,%eax + movl %eax,44(%edi) popl %edi movl \$0,%eax leave @@ -391,6 +395,8 @@ ___ljfault: movl 24(%edi),%ebp pushfl popl %ebx + movl 44(%edi),%eax + movl %eax,%fs:0 movw 42(%edi),%ax movw %ax,%ss movl 28(%edi),%esp @@ -415,7 +421,7 @@ _longjmp: movl %esp,%ebp movl 8(%ebp),%edi # address of buffer call stabilize_sig_stack - movl 44(%edi),%eax # get old signal stack + movl 48(%edi),%eax # get old signal stack movl %eax,$tls::stackptr(%ebx) # restore decl $tls::stacklock(%ebx) # relinquish lock xorl %eax,%eax @@ -430,6 +436,8 @@ _longjmp: movl 24(%edi),%ebp pushfl popl %ebx + movl 44(%edi),%eax + movl %eax,%fs:0 movw 42(%edi),%ax movw %ax,%ss movl 28(%edi),%esp diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 863f9e1f864..bcf331e8dd3 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -1166,7 +1166,6 @@ wait_sig (VOID *) SetEvent (wait_sig_inited); _sig_tls = &_my_tls; - _sig_tls->init_threadlist_exceptions (); sigproc_printf ("entering ReadFile loop, my_readsig %p, my_sendsig %p", my_readsig, my_sendsig); |