3 Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10 #define USE_SYS_TYPES_FD_SET
19 #include "exception.h"
27 bool acquired () {return lock.acquired ();}
28 sentry () {destroy = 0;}
29 sentry (DWORD wait) {destroy = lock.acquire (wait);}
30 ~sentry () {if (destroy) lock.release ();}
31 friend void _cygtls::init ();
34 muto NO_COPY sentry::lock;
36 static size_t NO_COPY nthreads;
38 #define THREADLIST_CHUNK 256
43 if (cygheap->threadlist)
44 memset (cygheap->threadlist, 0, cygheap->sthreads * sizeof (cygheap->threadlist[0]));
47 cygheap->sthreads = THREADLIST_CHUNK;
48 cygheap->threadlist = (_cygtls **) ccalloc_abort (HEAP_TLS, cygheap->sthreads,
49 sizeof (cygheap->threadlist[0]));
51 sentry::lock.init ("sentry_lock");
54 /* Two calls to get the stack right... */
56 _cygtls::call (DWORD (*func) (void *, void *), void *arg)
58 char buf[CYGTLS_PADSIZE];
59 /* Initialize this thread's ability to respond to things like
62 _my_tls.call2 (func, arg, buf);
66 _cygtls::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
68 init_thread (buf, func);
69 DWORD res = func (arg, buf);
71 /* Don't call ExitThread on the main thread since we may have been
72 dynamically loaded. */
73 if ((void *) func != (void *) dll_crt0_1
74 && (void *) func != (void *) dll_dllcrt0_1)
79 _cygtls::init_thread (void *x, DWORD (*func) (void *, void *))
83 memset (this, 0, sizeof (*this));
84 _REENT_INIT_PTR (&local_clib);
88 local_clib._stdin = _GLOBAL_REENT->_stdin;
89 local_clib._stdout = _GLOBAL_REENT->_stdout;
90 local_clib._stderr = _GLOBAL_REENT->_stderr;
91 local_clib.__sdidinit = _GLOBAL_REENT->__sdidinit ? -1 : 0;
92 local_clib.__cleanup = _GLOBAL_REENT->__cleanup;
93 local_clib.__sglue._niobs = 3;
94 local_clib.__sglue._iobs = &_GLOBAL_REENT->__sf[0];
98 thread_id = GetCurrentThreadId ();
99 initialized = CYGTLS_INITIALIZED;
100 errno_addr = &(local_clib._errno);
101 locals.cw_timer = NULL;
103 if ((void *) func == (void *) cygthread::stub
104 || (void *) func == (void *) cygthread::simplestub)
107 cygheap->user.reimpersonate ();
109 sentry here (INFINITE);
110 if (nthreads >= cygheap->sthreads)
112 cygheap->threadlist = (_cygtls **)
113 crealloc_abort (cygheap->threadlist, (cygheap->sthreads += THREADLIST_CHUNK)
114 * sizeof (cygheap->threadlist[0]));
115 memset (cygheap->threadlist + nthreads, 0, THREADLIST_CHUNK * sizeof (cygheap->threadlist[0]));
118 cygheap->threadlist[nthreads++] = this;
122 _cygtls::fixup_after_fork ()
129 stacklock = spinning = 0;
130 locals.select.sockevt = NULL;
131 locals.cw_timer = NULL;
135 #define free_local(x) \
143 _cygtls::remove (DWORD wait)
146 if (exit_state >= ES_FINAL)
149 debug_printf ("wait %p", wait);
151 /* FIXME: Need some sort of atthreadexit function to allow things like
152 select to control this themselves. */
154 /* Close handle and free memory used by select. */
155 if (locals.select.sockevt)
157 CloseHandle (locals.select.sockevt);
158 locals.select.sockevt = NULL;
159 free_local (select.ser_num);
160 free_local (select.w4);
162 /* Free memory used by network functions. */
163 free_local (ntoa_buf);
164 free_local (protoent_buf);
165 free_local (servent_buf);
166 free_local (hostent_buf);
167 /* Free temporary TLS path buffers. */
168 locals.pathbufs.destroy ();
173 if (here.acquired ())
175 for (size_t i = 0; i < nthreads; i++)
176 if (this == cygheap->threadlist[i])
179 cygheap->threadlist[i] = cygheap->threadlist[nthreads];
180 debug_printf ("removed %p element %d", this, i);
189 _cygtls::push (__stack_t addr)
191 *stackptr++ = (__stack_t) addr;
196 _cygtls::find_tls (int sig)
198 static int NO_COPY threadlist_ix;
200 debug_printf ("signal %d\n", sig);
201 sentry here (INFINITE);
207 if (efault.faulted ())
208 cygheap->threadlist[threadlist_ix]->remove (INFINITE);
210 while (++threadlist_ix < (int) nthreads)
211 if (sigismember (&(cygheap->threadlist[threadlist_ix]->sigwait_mask), sig))
213 res = cygheap->threadlist[threadlist_ix];
220 _cygtls::set_siginfo (sigpacket *pack)