aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/cygtls.cc125
1 files changed, 125 insertions, 0 deletions
diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc
new file mode 100644
index 0000000..2734cf5
--- /dev/null
+++ b/winsup/cygwin/cygtls.cc
@@ -0,0 +1,125 @@
+/* cygtls.h
+
+ Copyright 2003 Red Hat, Inc.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include "thread.h"
+#include "cygtls.h"
+#include "assert.h"
+#include <syslog.h>
+
+static _threadinfo NO_COPY dummy_thread;
+_threadinfo NO_COPY *_last_thread = &dummy_thread;
+
+CRITICAL_SECTION NO_COPY _threadinfo::protect_linked_list;
+
+void
+_threadinfo::set_state (bool is_exception)
+{
+ initialized = CYGTLS_INITIALIZED + is_exception;
+}
+
+void
+_threadinfo::reset_exception ()
+{
+ if (initialized == CYGTLS_EXCEPTION)
+ {
+#ifdef DEBUGGING
+ debug_printf ("resetting stack after an exception stack %p, stackptr %p", stack, stackptr);
+#endif
+ set_state (false);
+ stackptr--;
+ }
+}
+
+/* Two calls to get the stack right... */
+void
+_threadinfo::call (DWORD (*func) (void *, void *), void *arg)
+{
+ char buf[CYGTLS_PADSIZE];
+ call2 (func, arg, buf);
+}
+
+void
+_threadinfo::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
+{
+ _my_tls.init_thread (buf);
+ ExitThread (func (arg, buf));
+}
+
+void
+_threadinfo::init ()
+{
+ InitializeCriticalSection (&protect_linked_list);
+}
+
+void
+_threadinfo::init_thread (void *x)
+{
+ if (x)
+ {
+ memset (this, 0, sizeof (*this));
+ stackptr = stack;
+ if (_GLOBAL_REENT)
+ {
+ local_clib._stdin = _GLOBAL_REENT->_stdin;
+ local_clib._stdout = _GLOBAL_REENT->_stdout;
+ local_clib._stderr = _GLOBAL_REENT->_stderr;
+ local_clib.__sdidinit = _GLOBAL_REENT->__sdidinit;
+ local_clib.__cleanup = _GLOBAL_REENT->__cleanup;
+ }
+ local_clib._current_locale = "C";
+ locals.process_logmask = LOG_UPTO (LOG_DEBUG);
+ }
+
+ EnterCriticalSection (&protect_linked_list);
+ prev = _last_thread;
+ _last_thread->next = this;
+ _last_thread = this;
+ LeaveCriticalSection (&protect_linked_list);
+
+ set_state (false);
+ errno_addr = &(local_clib._errno);
+}
+
+void
+_threadinfo::remove ()
+{
+ EnterCriticalSection (&protect_linked_list);
+ if (prev)
+ {
+ prev->next = next;
+ if (next)
+ next->prev = prev;
+ if (this == _last_thread)
+ _last_thread = prev;
+ prev = next = NULL;
+ }
+ LeaveCriticalSection (&protect_linked_list);
+}
+
+void
+_threadinfo::push (__stack_t addr, bool exception)
+{
+ *stackptr++ = (__stack_t) addr;
+ set_state (exception);
+}
+
+__stack_t
+_threadinfo::pop ()
+{
+#ifdef DEBUGGING
+ assert (stackptr > stack);
+#endif
+ __stack_t res = *--stackptr;
+#ifdef DEBUGGING
+ *stackptr = 0;
+ debug_printf ("popped %p, stack %p, stackptr %p", res, stack, stackptr);
+#endif
+ return res;
+}
+