diff options
author | Christopher Faylor <me@cgf.cx> | 2012-08-09 19:58:53 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2012-08-09 19:58:53 +0000 |
commit | 52d2371da52be037af8020220650645df497d90d (patch) | |
tree | 981b4d875ae69b48fc6dfd2451f72c82002f14cd /winsup/cygwin/cygheap.cc | |
parent | cc02df128665f400e911e1f67e9963e827962914 (diff) | |
download | cygnal-52d2371da52be037af8020220650645df497d90d.tar.gz cygnal-52d2371da52be037af8020220650645df497d90d.tar.bz2 cygnal-52d2371da52be037af8020220650645df497d90d.zip |
* 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.
Diffstat (limited to 'winsup/cygwin/cygheap.cc')
-rw-r--r-- | winsup/cygwin/cygheap.cc | 99 |
1 files changed, 99 insertions, 0 deletions
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; +} |