qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH] qemu-thread: add TLS wrappers
Date: Tue, 16 Aug 2011 11:51:07 -0700	[thread overview]
Message-ID: <1313520667-26507-1-git-send-email-pbonzini@redhat.com> (raw)

Win32 emulated TLS is slow and is not available on all versions of GCC.
Actually, Win32 does have support for decent TLS, only GCC does not map
__thread to it.  The good news is, it's perfectly possible to declare
TLS variables with simple C code!

This patch adds wrappers to qemu-thread that will use __thread on POSIX
systems, and the .tls segment on Windows.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
	It does kinda uglify the declarations, but not too much IMO.
	Do we want to go this way?  It will certainly limit the number
	of bug reports we get.

 coroutine-win32.c   |    7 +++++--
 qemu-thread-posix.h |    4 ++++
 qemu-thread-win32.c |   17 +++++++++++++++++
 qemu-thread-win32.h |   40 +++++++++++++++++++++++++++++++++++++++-
 qemu-thread.h       |    2 ++
 5 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/coroutine-win32.c b/coroutine-win32.c
index 0e29448..7f58432 100644
--- a/coroutine-win32.c
+++ b/coroutine-win32.c
@@ -24,6 +24,7 @@
 
 #include "qemu-common.h"
 #include "qemu-coroutine-int.h"
+#include "qemu-thread.h"
 
 typedef struct
 {
@@ -33,8 +34,10 @@ typedef struct
     CoroutineAction action;
 } CoroutineWin32;
 
-static __thread CoroutineWin32 leader;
-static __thread Coroutine *current;
+static DEFINE_TLS(CoroutineWin32, tls_leader);
+static DEFINE_TLS(Coroutine *, tls_current);
+#define leader get_tls(tls_leader)
+#define current get_tls(tls_current)
 
 CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
                                       CoroutineAction action)
diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h
index d781ca6..2a302da 100644
--- a/qemu-thread-posix.h
+++ b/qemu-thread-posix.h
@@ -27,4 +27,8 @@ struct QemuThread {
     pthread_t thread;
 };
 
+#define DEFINE_TLS(type, x)	__thread type x
+#define DECLARE_TLS(type, x)	extern DEFINE_TLS(type, x)
+#define get_tls(x)		(x)
+
 #endif
diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
index f5891bd..3eb6b89 100644
--- a/qemu-thread-win32.c
+++ b/qemu-thread-win32.c
@@ -17,6 +17,23 @@
 #include <assert.h>
 #include <limits.h>
 
+/* TLS support, not exported by the mingw run-time library.  */
+
+int __attribute__((section(".tls$000"))) _tls_start = 0;
+int __attribute__((section(".tls$ZZZ"))) _tls_end = 0;
+int _tls_index = 0;
+
+const IMAGE_TLS_DIRECTORY _tls_used __attribute__((used, section(".rdata$T"))) =
+{
+ (ULONG)(ULONG_PTR) &_tls_start, // start of tls data
+ (ULONG)(ULONG_PTR) &_tls_end,   // end of tls data
+ (ULONG)(ULONG_PTR) &_tls_index, // address of tls_index
+ (ULONG) 0,                      // pointer to callbacks
+ (ULONG) 0,                      // size of tls zero fill
+ (ULONG) 0                       // characteristics
+};
+
+
 static void error_exit(int err, const char *msg)
 {
     char *pstr;
diff --git a/qemu-thread-win32.h b/qemu-thread-win32.h
index 6cb248f..2ffe7de 100644
--- a/qemu-thread-win32.h
+++ b/qemu-thread-win32.h
@@ -1,6 +1,7 @@
 #ifndef __QEMU_THREAD_WIN32_H
 #define __QEMU_THREAD_WIN32_H 1
-#include "windows.h"
+#include <windows.h>
+#include <winnt.h>
 
 struct QemuMutex {
     CRITICAL_SECTION lock;
@@ -27,4 +28,41 @@ struct QemuThread {
     void *ret;
 };
 
+typedef struct _TEB {
+  _NT_TIB NtTib;
+  void* EnvironmentPointer;
+  void *x[3];
+  char **ThreadLocalStoragePointer;
+} TEB, *PTEB;
+
+/* 1) The initial contents TLS variables is placed in the .tls section.  */
+
+#define DEFINE_TLS(type, x)	type tls__##x __attribute__((section(".tls$BBB")))
+
+/* 2) _tls_index holds the number of our module.  The executable should be
+   zero, DLLs are numbered 1 and up.  The loader fills it in for us.  */
+
+extern int _tls_index;
+extern int _tls_start;
+
+/* 3) Thus, Teb->ThreadLocalStoragePointer[_tls_index] is the base of
+   the TLS segment for this (thread, module) pair.  Each segment has
+   the same layout as this module's .tls segment and is initialized
+   with the content of the .tls segment; 0 is the _tls_start variable.
+   So, get_tls passes us the offset of the passed variable relative to
+   _tls_start, and we return that same offset plus the base of segment.  */
+
+static inline __attribute__((__pure__)) void *_get_tls(int offset)
+{
+    PTEB Teb = NtCurrentTeb();
+    return (char *)(Teb->ThreadLocalStoragePointer[_tls_index]) + offset;
+}
+
+/* 4) get_tls, in addition to computing the offset, returns an lvalue.
+      "I got it.  Magic."  */
+
+#define get_tls(x)		\
+  (*(__typeof__(tls__##x) *)    \
+    _get_tls((ULONG_PTR)&(tls__##x) - (ULONG_PTR)&_tls_start))
+
 #endif
diff --git a/qemu-thread.h b/qemu-thread.h
index ae75638..858c8cc 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -49,4 +49,6 @@ void qemu_thread_get_self(QemuThread *thread);
 int qemu_thread_is_self(QemuThread *thread);
 void qemu_thread_exit(void *retval);
 
+#define DECLARE_TLS(type, x)	extern DEFINE_TLS(type, x)
+
 #endif
-- 
1.7.6

             reply	other threads:[~2011-08-16 18:56 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-08-16 18:51 Paolo Bonzini [this message]
2011-08-17  4:36 ` [Qemu-devel] [PATCH] qemu-thread: add TLS wrappers Brad
2011-08-17  6:55   ` Paolo Bonzini
2011-08-17 17:28     ` Blue Swirl
2011-08-17 17:37       ` Paolo Bonzini
2011-08-17 19:00       ` Richard Henderson
2011-08-17 23:50         ` Brad
2011-08-17 23:51           ` Paolo Bonzini
2011-08-17 16:51 ` Stefan Hajnoczi
2011-08-17 17:13   ` Paolo Bonzini
2011-08-17 17:26     ` Stefan Hajnoczi
2011-08-17 17:28       ` Paolo Bonzini
2011-08-17 17:37         ` Blue Swirl
2011-08-17 17:45           ` Paolo Bonzini
2011-08-17 17:51             ` Blue Swirl
2011-08-17 18:03               ` Paolo Bonzini
2011-08-17 18:32                 ` malc
2011-08-17 23:41           ` Brad
2011-08-17 17:34     ` Blue Swirl
2011-08-17 17:38       ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1313520667-26507-1-git-send-email-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).