From 52d2371da52be037af8020220650645df497d90d Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Thu, 9 Aug 2012 19:58:53 +0000 Subject: [PATCH] * DevNotes: Add entry cgf-000014. * cygheap.cc (tls_sentry): Move here, rename from 'sentry' in cygtls.cc (tls_sentry::lock): Ditto. (nthreads): Move from cygtls.cc (THREADLIST_CHUNK): Ditto. (cygheap_init): Call init_tls_list(). (init_cygheap::init_tls_list): Define new function. (init_cygheap::add_tls): Ditto. (init_cygheap::remove_tls): Ditto. (init_cygheap::find_tls): Ditto. Semi-resurrect from _cygtls::find_tls. * cygheap.h (init_cygheap::init_tls_list): Declare new function. (init_cygheap::add_tls): Ditto. (init_cygheap::remove_tls): Ditto. (init_cygheap::find_tls): Ditto. * cygtls.cc (sentry): Delete. (sentry::lock): Ditto. (nthreads): Ditto. (THREADLIST_CHUNK): Ditto. (_cygtls::init): Delete definition. (_cygtls::init_thread): Call cygheap->add_tls() to add thread to global list. (_cygtls::remove): cygheap->remove_tls() to remove thread from global list. * cygtls.h (_cygtls::init): Delete declaration. * dcrt0.cc (dll_crt0_0): Delete call to _cygtls::init(). * exceptions.cc (sigpacket::process): When no thread is specified, try to find one via cygheap->find_tls. --- winsup/cygwin/ChangeLog | 31 +++++++++++ winsup/cygwin/DevNotes | 13 +++++ winsup/cygwin/cygheap.cc | 99 ++++++++++++++++++++++++++++++++++++ winsup/cygwin/cygheap.h | 4 ++ winsup/cygwin/cygtls.cc | 63 +---------------------- winsup/cygwin/cygtls.h | 1 - winsup/cygwin/dcrt0.cc | 2 - winsup/cygwin/exceptions.cc | 4 +- winsup/cygwin/release/1.7.17 | 3 +- 9 files changed, 153 insertions(+), 67 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index ee1a2ccca..e6b69ccd2 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,34 @@ +2012-08-09 Christopher Faylor + + * DevNotes: Add entry cgf-000014. + * cygheap.cc (tls_sentry): Move here, rename from 'sentry' in cygtls.cc + (tls_sentry::lock): Ditto. + (nthreads): Move from cygtls.cc + (THREADLIST_CHUNK): Ditto. + (cygheap_init): Call init_tls_list(). + (init_cygheap::init_tls_list): Define new function. + (init_cygheap::add_tls): Ditto. + (init_cygheap::remove_tls): Ditto. + (init_cygheap::find_tls): Ditto. Semi-resurrect from + _cygtls::find_tls. + * cygheap.h (init_cygheap::init_tls_list): Declare new function. + (init_cygheap::add_tls): Ditto. + (init_cygheap::remove_tls): Ditto. + (init_cygheap::find_tls): Ditto. + * cygtls.cc (sentry): Delete. + (sentry::lock): Ditto. + (nthreads): Ditto. + (THREADLIST_CHUNK): Ditto. + (_cygtls::init): Delete definition. + (_cygtls::init_thread): Call cygheap->add_tls() to add thread to global + list. + (_cygtls::remove): cygheap->remove_tls() to remove thread from global + list. + * cygtls.h (_cygtls::init): Delete declaration. + * dcrt0.cc (dll_crt0_0): Delete call to _cygtls::init(). + * exceptions.cc (sigpacket::process): When no thread is specified, try + to find one via cygheap->find_tls. + 2012-08-08 Corinna Vinschen * include/sys/wait.h (_wait): Define when building newlib. diff --git a/winsup/cygwin/DevNotes b/winsup/cygwin/DevNotes index e78348897..68d8320cd 100644 --- a/winsup/cygwin/DevNotes +++ b/winsup/cygwin/DevNotes @@ -1,3 +1,16 @@ +2012-08-09 cgf-000014 + +So, apparently I got it somewhat right before wrt signal handling. +Checking on linux, it appears that signals will be sent to a thread +which can accept the signal. So resurrecting and extending the +"find_tls" function is in order. This function will return the tls +of any thread which 1) is waiting for a signal with sigwait*() or +2) has the signal unmasked. + +In redoing this it became obvious that I had the class designation wrong +for the threadlist handling so I moved the manipulation of the global +threadlist into the cygheap where it logically belongs. + 2012-07-21 cgf-000013 These changes reflect a revamp of the "wait for signal" functionality diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index c7f1f6ab4..639f4e662 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -47,6 +47,23 @@ struct cygheap_entry char data[0]; }; +class tls_sentry +{ +public: + static muto lock; + int destroy; + void init (); + bool acquired () {return lock.acquired ();} + tls_sentry () {destroy = 0;} + tls_sentry (DWORD wait) {destroy = lock.acquire (wait);} + ~tls_sentry () {if (destroy) lock.release ();} +}; + +muto NO_COPY tls_sentry::lock; +static NO_COPY size_t nthreads; + +#define THREADLIST_CHUNK 256 + #define NBUCKETS (sizeof (cygheap->buckets) / sizeof (cygheap->buckets[0])) #define N0 ((_cmalloc_entry *) NULL) #define to_cmalloc(s) ((_cmalloc_entry *) (((char *) (s)) - (unsigned) (N0->data))) @@ -256,6 +273,7 @@ cygheap_init () cygheap->fdtab.init (); if (!cygheap->sigs) sigalloc (); + cygheap->init_tls_list (); } /* Copyright (C) 1997, 2000 DJ Delorie */ @@ -545,3 +563,84 @@ cygheap_user::set_name (const char *new_name) cfree_and_set (pdomain); cfree_and_set (pwinname); } + +void +init_cygheap::init_tls_list () +{ + if (threadlist) + memset (cygheap->threadlist, 0, cygheap->sthreads * sizeof (cygheap->threadlist[0])); + else + { + sthreads = THREADLIST_CHUNK; + threadlist = (_cygtls **) ccalloc_abort (HEAP_TLS, cygheap->sthreads, + sizeof (cygheap->threadlist[0])); + } + tls_sentry::lock.init ("thread_tls_sentry"); +} + +void +init_cygheap::add_tls (_cygtls *t) +{ + cygheap->user.reimpersonate (); + tls_sentry here (INFINITE); + if (nthreads >= cygheap->sthreads) + { + threadlist = (_cygtls **) + crealloc_abort (threadlist, (sthreads += THREADLIST_CHUNK) + * sizeof (threadlist[0])); + // memset (threadlist + nthreads, 0, THREADLIST_CHUNK * sizeof (threadlist[0])); + } + + threadlist[nthreads++] = t; +} + +void +init_cygheap::remove_tls (_cygtls *t, DWORD wait) +{ + tls_sentry here (wait); + if (here.acquired ()) + { + for (size_t i = 0; i < nthreads; i++) + if (t == threadlist[i]) + { + if (i < --nthreads) + threadlist[i] = threadlist[nthreads]; + debug_only_printf ("removed %p element %d", this, i); + break; + } + } +} + +_cygtls * +init_cygheap::find_tls (int sig) +{ + debug_printf ("sig %d\n", sig); + tls_sentry here (INFINITE); + + static int NO_COPY threadlist_ix; + + _cygtls *t = _main_tls; + + myfault efault; + if (efault.faulted ()) + threadlist[threadlist_ix]->remove (INFINITE); + else + { + threadlist_ix = -1; + while (++threadlist_ix < (int) nthreads) + if (sigismember (&(threadlist[threadlist_ix]->sigwait_mask), sig)) + { + t = cygheap->threadlist[threadlist_ix]; + goto out; + } + threadlist_ix = -1; + while (++threadlist_ix < (int) nthreads) + if (!sigismember (&(threadlist[threadlist_ix]->sigmask), sig)) + { + t = cygheap->threadlist[threadlist_ix]; + break; + } + } +out: + return t; +} diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index f2b0cd9ec..e03774ffd 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -396,6 +396,10 @@ struct init_cygheap: public mini_cygheap hook_chain hooks; void close_ctty (); void init_installation_root (); + void init_tls_list () __attribute__ ((regparm (1)));; + void add_tls (_cygtls *) __attribute__ ((regparm (2))); + void remove_tls (_cygtls *, DWORD) __attribute__ ((regparm (3))); + _cygtls *find_tls (int) __attribute__ ((regparm (2))); }; diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index da48622f1..abda77c5f 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -19,39 +19,6 @@ details. */ #include "sigproc.h" #include "exception.h" -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 _cygtls::init (); -}; - -muto NO_COPY sentry::lock; - -static size_t NO_COPY nthreads; - -#define THREADLIST_CHUNK 256 - -void -_cygtls::init () -{ - if (cygheap->threadlist) - memset (cygheap->threadlist, 0, cygheap->sthreads * sizeof (cygheap->threadlist[0])); - else - { - cygheap->sthreads = THREADLIST_CHUNK; - cygheap->threadlist = (_cygtls **) ccalloc_abort (HEAP_TLS, cygheap->sthreads, - sizeof (cygheap->threadlist[0])); - } - sentry::lock.init ("sentry_lock"); -} - /* Two calls to get the stack right... */ void _cygtls::call (DWORD (*func) (void *, void *), void *arg) @@ -167,18 +134,7 @@ _cygtls::init_thread (void *x, DWORD (*func) (void *, void *)) || (void *) func == (void *) cygthread::simplestub) return; - cygheap->user.reimpersonate (); - - sentry here (INFINITE); - if (nthreads >= cygheap->sthreads) - { - cygheap->threadlist = (_cygtls **) - crealloc_abort (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; + cygheap->add_tls (this); } void @@ -237,22 +193,7 @@ _cygtls::remove (DWORD wait) free_local (hostent_buf); /* Free temporary TLS path buffers. */ locals.pathbufs.destroy (); - - do - { - sentry here (wait); - if (here.acquired ()) - { - for (size_t i = 0; i < nthreads; i++) - if (this == cygheap->threadlist[i]) - { - if (i < --nthreads) - cygheap->threadlist[i] = cygheap->threadlist[nthreads]; - debug_printf ("removed %p element %d", this, i); - break; - } - } - } while (0); + cygheap->remove_tls (this, wait); remove_wq (wait); } diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h index 3db7e10b8..d683cf837 100644 --- a/winsup/cygwin/cygtls.h +++ b/winsup/cygwin/cygtls.h @@ -204,7 +204,6 @@ public: unsigned initialized; /*gentls_offsets*/ - static void init (); void init_thread (void *, DWORD (*) (void *, void *)); static void call (DWORD (*) (void *, void *), void *); void remove (DWORD); diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 7e32de0ef..0cda2e5d5 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -773,8 +773,6 @@ dll_crt0_0 () user_data->threadinterface->Init (); - _cygtls::init (); - _main_tls = &_my_tls; /* Initialize signal processing here, early, in the hopes that the creation diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index afbbff4cb..649574fc2 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -1170,8 +1170,8 @@ sigpacket::process () sigproc_printf ("using tls %p", tls); else { - tls = _main_tls; - sigproc_printf ("using main tls %p", _main_tls); + tls = cygheap->find_tls (si.si_signo); + sigproc_printf ("using tls %p", tls); } if (si.si_signo == SIGKILL) diff --git a/winsup/cygwin/release/1.7.17 b/winsup/cygwin/release/1.7.17 index 13ccae223..90df145be 100644 --- a/winsup/cygwin/release/1.7.17 +++ b/winsup/cygwin/release/1.7.17 @@ -1,9 +1,10 @@ Bug fixes: ---------- -- Revamp signals so that signals-to-threads more closely mimic linux +- Revamp signals so that signals-to-threads more closely mimic Linux operation. First step of fix for: http://cygwin.com/ml/cygwin/2012-05/msg00186.html + as well as observed Linux behavior. - Revert to only creating a new session leader when we know that a console process is started in the background.