Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2012-08-09 23:58:53 +0400
committerChristopher Faylor <me@cgf.cx>2012-08-09 23:58:53 +0400
commit52d2371da52be037af8020220650645df497d90d (patch)
tree981b4d875ae69b48fc6dfd2451f72c82002f14cd /winsup/cygwin/cygheap.cc
parentcc02df128665f400e911e1f67e9963e827962914 (diff)
* 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.cc99
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;
+}