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
next 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).