Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'windows-threads' into enhanced-windows-threads

  • Loading branch information...
commit 18c02b209f500c89350830a70a21c545d156fe21 2 parents c2e9f60 + 42b900d
@dmitryvk authored
View
2  src/compiler/x86/parms.lisp
@@ -388,4 +388,4 @@
;;; cf the sparc PARMS.LISP
(defparameter *assembly-unit-length* 8)
-(defconstant +win32-tib-arbitrary-field-offset+ #x14)
+(defconstant +win32-tib-arbitrary-field-offset+ #.(+ #xE10 (* 4 63)))
View
1  src/runtime/runtime.c
@@ -338,6 +338,7 @@ main(int argc, char *argv[], char *envp[])
const char *sbcl_home = getenv("SBCL_HOME");
#if defined(LISP_FEATURE_WIN32) && defined(LISP_FEATURE_SB_THREAD)
+ os_preinit();
pthreads_win32_init();
#endif
View
1  src/runtime/runtime.h
@@ -37,6 +37,7 @@
#endif
#if defined(LISP_FEATURE_WIN32) && defined(LISP_FEATURE_SB_THREAD)
+void os_preinit();
void map_gc_page();
void unmap_gc_page();
#endif
View
2  src/runtime/thread.h
@@ -263,7 +263,7 @@ static inline struct thread *arch_os_get_current_thread(void)
#if defined(LISP_FEATURE_X86)
register struct thread *me=0;
#if defined(LISP_FEATURE_WIN32) && defined(LISP_FEATURE_SB_THREAD)
- __asm__ __volatile__ ("movl %%fs:0x14, %0" : "=r"(me) :);
+ __asm__ __volatile__ ("movl %%fs:0xE10+(4*63), %0" : "=r"(me) :);
return me;
#endif
if(all_threads) {
View
71 src/runtime/win32-os.c
@@ -204,6 +204,77 @@ void unmap_gc_page()
}
#endif
+#if defined(LISP_FEATURE_SB_THREAD)
+/* We want to get a slot in TIB that (1) is available at constant
+ offset, (2) is our private property, so libraries wouldn't legally
+ override it, (3) contains something predefined for threads created
+ out of our sight.
+
+ Low 64 TLS slots are adressable directly, starting with
+ FS:[#xE10]. When SBCL runtime is initialized, some of the low slots
+ may be already in use by its prerequisite DLLs, as DllMain()s and
+ TLS callbacks have been called already. But slot 63 is unlikely to
+ be reached at this point: one slot per DLL that needs it is the
+ common practice, and many system DLLs use predefined TIB-based
+ areas outside conventional TLS storage and don't need TLS slots.
+ With our current dependencies, even slot 2 is observed to be free
+ (as of WinXP and wine).
+
+ Now we'll call TlsAlloc() repeatedly until slot 63 is officially
+ assigned to us, then TlsFree() all other slots for normal use. TLS
+ slot 63, alias FS:[#.(+ #xE10 (* 4 63))], now belongs to us.
+
+ To summarize, let's list the assumptions we make:
+
+ - TIB, which is FS segment base, contains first 64 TLS slots at the
+ offset #xE10 (i.e. TIB layout compatibility);
+ - TLS slots are allocated from lower to higher ones;
+ - All libraries together with CRT startup have not requested 64
+ slots yet.
+
+ All these assumptions together don't seem to be less warranted than
+ the availability of TIB arbitrary data slot for our use. There are
+ some more reasons to prefer slot 63 over TIB arbitrary data: (1) if
+ our assumptions for slot 63 are violated, it will be detected at
+ startup instead of causing some system-specific unreproducible
+ problems afterwards, depending on OS and loaded foreign libraries;
+ (2) if getting slot 63 reliably with our current approach will
+ become impossible for some future Windows version, we can add TLS
+ callback directory to SBCL binary; main image TLS callback is
+ started before _any_ TLS slot is allocated by libraries, and
+ some C compiler vendors rely on this fact. */
+
+void os_preinit()
+{
+ DWORD slots[TLS_MINIMUM_AVAILABLE];
+ DWORD key;
+ int n_slots = 0, i;
+ for (i=0; i<TLS_MINIMUM_AVAILABLE; ++i) {
+ key = TlsAlloc();
+ if (key == OUR_TLS_INDEX) {
+ if (TlsGetValue(key)!=NULL)
+ lose("TLS slot assertion failed: fresh slot value is not NULL");
+ TlsSetValue(OUR_TLS_INDEX, (intptr_t)0xFEEDBAC4);
+ if ((intptr_t)(void*)arch_os_get_current_thread()!=(intptr_t)0xFEEDBAC4)
+ lose("TLS slot assertion failed: TIB layout change detected");
+ TlsSetValue(OUR_TLS_INDEX, (intptr_t)0xDEADBEAD);
+ if ((intptr_t)(void*)arch_os_get_current_thread()!=(intptr_t)0xDEADBEAD)
+ lose("TLS slot assertion failed: TIB content unstable");
+ TlsSetValue(OUR_TLS_INDEX, NULL);
+ break;
+ }
+ slots[n_slots++]=key;
+ }
+ for (i=0; i<n_slots; ++i) {
+ TlsFree(i);
+ }
+ if (key!=OUR_TLS_INDEX) {
+ lose("TLS slot assertion failed: slot 63 is unavailable "
+ "(last TlsAlloc() returned %u)",key);
+ }
+}
+#endif
+
void os_init(char *argv[], char *envp[])
{
SYSTEM_INFO system_info;
View
1  src/runtime/win32-os.h
@@ -34,6 +34,7 @@ typedef void *siginfo_t;
#define OS_VM_PROT_WRITE 2
#define OS_VM_PROT_EXECUTE 4
+#define OUR_TLS_INDEX 63
#define SIG_MEMORY_FAULT SIGSEGV
#define SIG_STOP_FOR_GC (SIGRTMIN+1)
View
2  src/runtime/x86-assem.S
@@ -286,7 +286,7 @@ Ldone:
/* Save binding stack pointer */
subl $4, %esp
pushl %eax
- movl %fs:0x14, %eax
+ movl %fs:0xE10+(4*63), %eax
movl THREAD_BINDING_STACK_POINTER_OFFSET(%eax), %eax
movl %eax, 4(%esp)
popl %eax
View
2  src/runtime/x86-win32-os.c
@@ -85,7 +85,7 @@ int arch_os_thread_init(struct thread *thread)
}
#ifdef LISP_FEATURE_SB_THREAD
- __asm__ __volatile__ ("movl %0, %%fs:0x14" : : "r" (thread));
+ TlsSetValue(OUR_TLS_INDEX,thread);
#endif
return 1;
Please sign in to comment.
Something went wrong with that request. Please try again.