diff options
Diffstat (limited to 'winsup/cygwin/how-cygtls-works.txt')
-rw-r--r-- | winsup/cygwin/how-cygtls-works.txt | 75 |
1 files changed, 0 insertions, 75 deletions
diff --git a/winsup/cygwin/how-cygtls-works.txt b/winsup/cygwin/how-cygtls-works.txt deleted file mode 100644 index 69363f1fb..000000000 --- a/winsup/cygwin/how-cygtls-works.txt +++ /dev/null @@ -1,75 +0,0 @@ -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. |