]> sourceware.org Git - newlib-cygwin.git/commitdiff
* dcrt0.cc (cygwin_dll_init): Now initializes main_environ and cygtls. Comment
authorChristopher Faylor <me@cgf.cx>
Sat, 4 Jun 2005 02:11:50 +0000 (02:11 +0000)
committerChristopher Faylor <me@cgf.cx>
Sat, 4 Jun 2005 02:11:50 +0000 (02:11 +0000)
to explain the caveats of this method.
* how-cygtls-works.txt: New file.

winsup/cygwin/ChangeLog
winsup/cygwin/dcrt0.cc
winsup/cygwin/dlfcn.cc
winsup/cygwin/how-cygtls-works.txt [new file with mode: 0644]

index fc409bb92ede808be69042892945f3b46974bb4e..2578bf37f77fb8ffb9894060e66cfa5f73d8ef81 100644 (file)
@@ -1,3 +1,9 @@
+2005-06-03  Max Kaehn <slothman@electric-cloud.com>
+
+       * dcrt0.cc (cygwin_dll_init): Now initializes main_environ and cygtls.
+       Comment to explain the caveats of this method.
+       * how-cygtls-works.txt: New file.
+
 2005-06-02  Christopher Faylor  <cgf@timesys.com>
 
        * dlfcn.cc (get_full_path_of_dll): Use a relative path when converting
index 4f643ae1e14c471e343a0156e0620b47329ad931..457661000e8f90de2d990b7f405043d37b94f7de 100644 (file)
@@ -955,7 +955,15 @@ dll_crt0 (per_process *uptr)
   _dll_crt0 ();
 }
 
-/* This must be called by anyone who uses LoadLibrary to load cygwin1.dll */
+/* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
+ * You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
+ * calling this function, and that storage must not be overwritten until you
+ * unload cygwin1.dll, as it is used for _my_tls.  It is best to load
+ * cygwin1.dll before spawning any additional threads in your process.
+ *
+ * See winsup/testsuite/cygload for an example of how to use cygwin1.dll
+ * from MSVC and non-cygwin MinGW applications.
+ */
 extern "C" void
 cygwin_dll_init ()
 {
@@ -974,6 +982,9 @@ cygwin_dll_init ()
   user_data->envptr = &envp;
   user_data->fmode_ptr = &_fmode;
 
+  main_environ = user_data->envptr;
+  *main_environ = NULL;
+  initialize_main_tls((char *)&_my_tls);
   dll_crt0_1 (NULL);
 }
 
index 23e4aed0521a21dc44894b99221b0872be2c23bc..27daed893d5502f4ff29be06d74aaf5e725e527c 100644 (file)
@@ -68,8 +68,8 @@ get_full_path_of_dll (const char* str, char *name)
 
   if (isabspath (name) ||
       (ret = check_path_access ("LD_LIBRARY_PATH=", name, real_filename)
-             ?: check_path_access ("/usr/bin:/usr/lib", name, real_filename)) == NULL)
-    real_filename.check (name);        /* Convert */
+             ?: check_path_access ("/usr/lib", name, real_filename)) == NULL)
+    real_filename.check (name, PC_SYM_FOLLOW | PC_NOFULL | PC_NULLEMPTY);      /* Convert */
 
   if (!real_filename.error)
     ret = strcpy (name, real_filename);
diff --git a/winsup/cygwin/how-cygtls-works.txt b/winsup/cygwin/how-cygtls-works.txt
new file mode 100644 (file)
index 0000000..69363f1
--- /dev/null
@@ -0,0 +1,75 @@
+Copyright 2005 Red Hat Inc., Max Kaehn
+
+All cygwin threads have separate context in an object of class _cygtls.  The
+storage for this object is kept on the stack in the bottom CYGTLS_PADSIZE
+bytes.  Each thread references the storage via the Thread Environment Block
+(aka Thread Information Block), which Windows maintains for each user thread
+in the system, with the address in the FS segment register.  The memory
+is laid out as in the NT_TIB structure from <w32api/winnt.h>:
+
+typedef struct _NT_TIB {
+       struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
+       PVOID StackBase;
+       PVOID StackLimit;
+       PVOID SubSystemTib;
+       _ANONYMOUS_UNION union {
+               PVOID FiberData;
+               DWORD Version;
+       } DUMMYUNIONNAME;
+       PVOID ArbitraryUserPointer;
+       struct _NT_TIB *Self;
+} NT_TIB,*PNT_TIB;
+
+Cygwin sees it like this:
+
+extern exception_list *_except_list asm ("%fs:0");      // exceptions.cc
+extern char *_tlsbase __asm__ ("%fs:4");                // cygtls.h
+extern char *_tlstop __asm__ ("%fs:8");                 // cygtls.h
+
+And accesses cygtls like this:
+
+#define _my_tls (((_cygtls *) _tlsbase)[-1])            // cygtls.h
+
+
+Initialization always goes through _cygtls::init_thread().  It works
+in the following ways:
+
+* In the main thread, _dll_crt0() provides CYGTLS_PADSIZE bytes on the stack
+  and passes them to initialize_main_tls(), which calls _cygtls::init_thread().
+  It then calls dll_crt0_1(), which terminates with cygwin_exit() rather than
+  by returning, so the storage never goes out of scope.
+
+  If you load cygwin1.dll dynamically from a non-cygwin application, it is
+  vital that the bottom CYGTLS_PADSIZE bytes of the stack are not in use
+  before you call cygwin_dll_init().  See winsup/testsuite/cygload for
+  more information.
+
+* Threads other than the main thread receive DLL_THREAD_ATTACH messages
+  to dll_entry() (in init.cc).
+  - dll_entry() calls munge_threadfunc(), which grabs the function pointer
+    for the thread from the stack frame and substitutes threadfunc_fe(),
+  - which then passes the original function pointer to _cygtls::call(),
+  - which then allocates CYGTLS_PADSIZE bytes on the stack and hands them
+    to call2(),
+  - which allocates an exception_list object on the stack and hands it to
+    init_exceptions() (in exceptions.cc), which attaches it to the end of
+    the list of exception handlers, changing _except_list (aka
+    tib->ExceptionList), then passes the cygtls storage to init_thread().
+    call2() calls ExitThread() instead of returning, so the storage never
+    goes out of scope.
+
+Note that the padding isn't necessarily going to be just where the _cygtls
+structure lives; it just makes sure there's enough room on the stack when the
+CYGTLS_PADSIZE bytes down from there are overwritten.
+
+
+Debugging
+
+You can examine the segment registers in gdb via "info w32 selector $fs"
+(which is using GetThreadSelectorEntry()) to get results like this:
+
+    Selector $fs
+    0x03b: base=0x7ffdd000 limit=0x00000fff 32-bit Data (Read/Write, Exp-up)
+    Priviledge level = 3. Byte granular.
+
+"x/3x 0x7ffdd000" will give you _except_list, _tlsbase, and _tlstop.
This page took 0.035547 seconds and 5 git commands to generate.