3 Copyright 2003, 2004, 2005 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
11 #define USE_SYS_TYPES_FD_SET
19 #include "exceptions.h"
35 bool acquired () {return lock.acquired ();}
36 sentry () {destroy = 0;}
37 sentry (DWORD wait) {destroy = lock.acquire (wait);}
38 ~sentry () {if (destroy) lock.release ();}
39 friend void _cygtls::init ();
42 muto NO_COPY sentry::lock;
44 static size_t NO_COPY nthreads;
46 #define THREADLIST_CHUNK 256
51 if (cygheap->threadlist)
52 memset (cygheap->threadlist, 0, cygheap->sthreads * sizeof (cygheap->threadlist[0]));
55 cygheap->sthreads = THREADLIST_CHUNK;
56 cygheap->threadlist = (_cygtls **) ccalloc (HEAP_TLS, cygheap->sthreads,
57 sizeof (cygheap->threadlist[0]));
59 sentry::lock.init ("sentry_lock");
63 _cygtls::set_state (bool is_exception)
65 initialized = CYGTLS_INITIALIZED + is_exception;
69 _cygtls::reset_exception ()
71 if (initialized == CYGTLS_EXCEPTION)
74 debug_printf ("resetting stack after an exception stack %p, stackptr %p", stack, stackptr);
80 /* Two calls to get the stack right... */
82 _cygtls::call (DWORD (*func) (void *, void *), void *arg)
84 char buf[CYGTLS_PADSIZE];
85 call2 (func, arg, buf);
89 _cygtls::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
91 exception_list except_entry;
92 /* Initialize this thread's ability to respond to things like
94 init_exceptions (&except_entry);
95 _my_tls.init_thread (buf, func);
96 DWORD res = func (arg, buf);
97 _my_tls.remove (INFINITE);
102 _cygtls::init_thread (void *x, DWORD (*func) (void *, void *))
106 memset (this, 0, CYGTLS_PADSIZE);
110 local_clib._stdin = _GLOBAL_REENT->_stdin;
111 local_clib._stdout = _GLOBAL_REENT->_stdout;
112 local_clib._stderr = _GLOBAL_REENT->_stderr;
113 local_clib.__sdidinit = _GLOBAL_REENT->__sdidinit ? -1 : 0;
114 local_clib.__cleanup = _GLOBAL_REENT->__cleanup;
115 local_clib.__sglue._niobs = 3;
116 local_clib.__sglue._iobs = &_GLOBAL_REENT->__sf[0];
118 local_clib._current_locale = "C";
119 locals.process_logmask = LOG_UPTO (LOG_DEBUG);
122 locals.exitsock = INVALID_SOCKET;
124 errno_addr = &(local_clib._errno);
126 if ((void *) func == (void *) cygthread::stub
127 || (void *) func == (void *) cygthread::simplestub)
130 if (wincap.has_security ())
131 cygheap->user.reimpersonate ();
133 sentry here (INFINITE);
134 if (nthreads >= cygheap->sthreads)
136 cygheap->threadlist = (_cygtls **)
137 crealloc (cygheap->threadlist, (cygheap->sthreads += THREADLIST_CHUNK)
138 * sizeof (cygheap->threadlist[0]));
139 memset (cygheap->threadlist + nthreads, 0, THREADLIST_CHUNK * sizeof (cygheap->threadlist[0]));
142 cygheap->threadlist[nthreads++] = this;
146 _cygtls::fixup_after_fork ()
153 stacklock = spinning = 0;
154 locals.exitsock = INVALID_SOCKET;
158 #define free_local(x) \
166 _cygtls::remove (DWORD wait)
168 debug_printf ("wait %p", wait);
169 if (!locals.exitsock)
173 /* FIXME: Need some sort of atthreadexit function to allow things like
174 select to control this themselves. */
175 if (locals.exitsock != INVALID_SOCKET)
177 closesocket (locals.exitsock);
178 locals.exitsock = (SOCKET) NULL;
180 free_local (process_ident);
181 free_local (ntoa_buf);
182 free_local (protoent_buf);
183 free_local (servent_buf);
184 free_local (hostent_buf);
190 if (here.acquired ())
192 for (size_t i = 0; i < nthreads; i++)
193 if (this == cygheap->threadlist[i])
196 cygheap->threadlist[i] = cygheap->threadlist[nthreads];
197 debug_printf ("removed %p element %d", this, i);
206 _cygtls::push (__stack_t addr, bool exception)
210 *stackptr++ = (__stack_t) addr;
213 set_state (exception);
216 #define BAD_IX ((size_t) -1)
217 static size_t NO_COPY threadlist_ix = BAD_IX;
220 _cygtls::find_tls (int sig)
222 debug_printf ("sig %d\n", sig);
223 sentry here (INFINITE);
224 __asm__ volatile (".equ _threadlist_exception_return,.");
226 for (threadlist_ix = 0; threadlist_ix < nthreads; threadlist_ix++)
227 if (sigismember (&(cygheap->threadlist[threadlist_ix]->sigwait_mask), sig))
229 res = cygheap->threadlist[threadlist_ix];
232 threadlist_ix = BAD_IX;
237 _cygtls::set_siginfo (sigpacket *pack)
242 extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD);
244 handle_threadlist_exception (EXCEPTION_RECORD *e, void *frame, CONTEXT *c, void *)
246 if (e->ExceptionCode != STATUS_ACCESS_VIOLATION)
248 system_printf ("unhandled exception %p at %p", e->ExceptionCode, c->Eip);
253 if (threadlist_ix == BAD_IX)
255 system_printf ("called with threadlist_ix %d", BAD_IX);
259 if (!here.acquired ())
261 system_printf ("couldn't aquire muto");
265 extern void *threadlist_exception_return;
266 cygheap->threadlist[threadlist_ix]->remove (INFINITE);
268 RtlUnwind (frame, threadlist_exception_return, e, 0);
273 _cygtls::init_threadlist_exceptions (exception_list *el)
275 extern void init_exception_handler (exception_list *, exception_handler *);
276 init_exception_handler (el, handle_threadlist_exception);