qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Hajnoczi <stefanha@redhat.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
	Stefan Hajnoczi <stefanha@redhat.com>,
	Paolo Bonzini <pbonzini@redhat.com>
Subject: [Qemu-devel] [PULL v2 31/44] coroutine-ucontext: use __thread
Date: Mon, 12 Jan 2015 16:40:21 +0000	[thread overview]
Message-ID: <1421080834-14724-32-git-send-email-stefanha@redhat.com> (raw)
In-Reply-To: <1421080834-14724-1-git-send-email-stefanha@redhat.com>

From: Paolo Bonzini <pbonzini@redhat.com>

ELF thread local storage is about 10% faster on tests/test-coroutine's
perf/cost test.  The timing on my machine is 190ns per iteration with
pthread TLS, 170 with ELF TLS.

Based on a patch by Kevin Wolf and Peter Lieven, but redone to follow
the model of coroutine-win32.c (including the important "noinline"
attribute!).

Platforms without thread-local storage (OpenBSD probably?) will need
a new-enough GCC for this to compile, in order to use the same emutls
support that Windows already relies on.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Message-id: 1417518350-6167-2-git-send-email-pbonzini@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 coroutine-ucontext.c | 69 +++++++++++++++-------------------------------------
 1 file changed, 19 insertions(+), 50 deletions(-)

diff --git a/coroutine-ucontext.c b/coroutine-ucontext.c
index 4bf2cde..259fcb4 100644
--- a/coroutine-ucontext.c
+++ b/coroutine-ucontext.c
@@ -25,7 +25,6 @@
 #include <stdlib.h>
 #include <setjmp.h>
 #include <stdint.h>
-#include <pthread.h>
 #include <ucontext.h>
 #include "qemu-common.h"
 #include "block/coroutine_int.h"
@@ -48,15 +47,8 @@ typedef struct {
 /**
  * Per-thread coroutine bookkeeping
  */
-typedef struct {
-    /** Currently executing coroutine */
-    Coroutine *current;
-
-    /** The default coroutine */
-    CoroutineUContext leader;
-} CoroutineThreadState;
-
-static pthread_key_t thread_state_key;
+static __thread CoroutineUContext leader;
+static __thread Coroutine *current;
 
 /*
  * va_args to makecontext() must be type 'int', so passing
@@ -68,36 +60,6 @@ union cc_arg {
     int i[2];
 };
 
-static CoroutineThreadState *coroutine_get_thread_state(void)
-{
-    CoroutineThreadState *s = pthread_getspecific(thread_state_key);
-
-    if (!s) {
-        s = g_malloc0(sizeof(*s));
-        s->current = &s->leader.base;
-        pthread_setspecific(thread_state_key, s);
-    }
-    return s;
-}
-
-static void qemu_coroutine_thread_cleanup(void *opaque)
-{
-    CoroutineThreadState *s = opaque;
-
-    g_free(s);
-}
-
-static void __attribute__((constructor)) coroutine_init(void)
-{
-    int ret;
-
-    ret = pthread_key_create(&thread_state_key, qemu_coroutine_thread_cleanup);
-    if (ret != 0) {
-        fprintf(stderr, "unable to create leader key: %s\n", strerror(errno));
-        abort();
-    }
-}
-
 static void coroutine_trampoline(int i0, int i1)
 {
     union cc_arg arg;
@@ -193,15 +155,23 @@ void qemu_coroutine_delete(Coroutine *co_)
     g_free(co);
 }
 
-CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
-                                      CoroutineAction action)
+/* This function is marked noinline to prevent GCC from inlining it
+ * into coroutine_trampoline(). If we allow it to do that then it
+ * hoists the code to get the address of the TLS variable "current"
+ * out of the while() loop. This is an invalid transformation because
+ * the sigsetjmp() call may be called when running thread A but
+ * return in thread B, and so we might be in a different thread
+ * context each time round the loop.
+ */
+CoroutineAction __attribute__((noinline))
+qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
+                      CoroutineAction action)
 {
     CoroutineUContext *from = DO_UPCAST(CoroutineUContext, base, from_);
     CoroutineUContext *to = DO_UPCAST(CoroutineUContext, base, to_);
-    CoroutineThreadState *s = coroutine_get_thread_state();
     int ret;
 
-    s->current = to_;
+    current = to_;
 
     ret = sigsetjmp(from->env, 0);
     if (ret == 0) {
@@ -212,14 +182,13 @@ CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
 
 Coroutine *qemu_coroutine_self(void)
 {
-    CoroutineThreadState *s = coroutine_get_thread_state();
-
-    return s->current;
+    if (!current) {
+        current = &leader.base;
+    }
+    return current;
 }
 
 bool qemu_in_coroutine(void)
 {
-    CoroutineThreadState *s = pthread_getspecific(thread_state_key);
-
-    return s && s->current->caller;
+    return current && current->caller;
 }
-- 
2.1.0

  parent reply	other threads:[~2015-01-12 17:42 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-12 16:39 [Qemu-devel] [PULL v2 00/44] Block patches Stefan Hajnoczi
2015-01-12 16:39 ` [Qemu-devel] [PULL v2 01/44] qemu-iotests: Remove 091 from quick group Stefan Hajnoczi
2015-01-12 16:39 ` [Qemu-devel] [PULL v2 02/44] qemu-iotests: Speed up make check-block Stefan Hajnoczi
2015-01-12 16:39 ` [Qemu-devel] [PULL v2 03/44] block: mark AioContext as recursive Stefan Hajnoczi
2015-01-12 16:39 ` [Qemu-devel] [PULL v2 04/44] block: do not allocate an iovec per read of a growable/zero_after_eof BDS Stefan Hajnoczi
2015-01-12 16:39 ` [Qemu-devel] [PULL v2 05/44] block: replace g_new0 with g_new for bottom half allocation Stefan Hajnoczi
2015-01-12 16:39 ` [Qemu-devel] [PULL v2 06/44] checkpatch: Brace handling on multi-line condition Stefan Hajnoczi
2015-01-12 16:39 ` [Qemu-devel] [PULL v2 07/44] block: Get full backing filename from string Stefan Hajnoczi
2015-01-12 16:39 ` [Qemu-devel] [PULL v2 08/44] block: JSON filenames and relative backing files Stefan Hajnoczi
2015-01-12 16:39 ` [Qemu-devel] [PULL v2 09/44] block: Relative backing file for image creation Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 10/44] block/vmdk: Relative backing file for creation Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 11/44] iotests: Add test for relative backing file names Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 12/44] qapi: Fix document for BlockStats.node-name Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 13/44] block: fix spoiling all dirty bitmaps by mirror and migration Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 14/44] qapi: Comment version info in TransactionAction Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 15/44] qmp: Add command 'blockdev-backup' Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 16/44] block: Add blockdev-backup to transaction Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 17/44] qemu-iotests: Test blockdev-backup in 055 Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 18/44] iotests: Filter out "I/O thread spun..." warning Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 19/44] migration/block: fix pending() return value Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 20/44] libqos: Convert malloc-pc allocator to a generic allocator Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 21/44] libqos: Change use of pointers to uint64_t in virtio Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 22/44] tests: Prepare virtio-blk-test for multi-arch implementation Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 23/44] libqos: Remove PCI assumptions in constants of virtio driver Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 24/44] libqos: Add malloc generic Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 25/44] libqos: Add virtio MMIO support Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 26/44] block/raw-posix.c: Fixes raw_getlength() on Mac OS X so that it reports the correct length of a real CD Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 27/44] .gitignore: Ignore generated "common.env" Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 28/44] qemu-iotests: Replace "/bin/true" with "true" Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 29/44] qemu-iotests: Add "_supported_os Linux" to 058 Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 30/44] qemu-iotests: Add supported os parameter for python tests Stefan Hajnoczi
2015-01-12 16:40 ` Stefan Hajnoczi [this message]
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 32/44] qemu-thread: add per-thread atexit functions Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 33/44] test-coroutine: avoid overflow on 32-bit systems Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 34/44] QSLIST: add lock-free operations Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 35/44] coroutine: rewrite pool to avoid mutex Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 36/44] coroutine: drop qemu_coroutine_adjust_pool_size Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 37/44] coroutine: try harder not to delete coroutines Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 38/44] block: limited request size in write zeroes unsupported path Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 39/44] block: Split BLOCK_OP_TYPE_COMMIT to BLOCK_OP_TYPE_COMMIT_{SOURCE, TARGET} Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 40/44] ide: Implement VPD response for ATAPI Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 41/44] nvme: Fix get/set number of queues feature Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 42/44] MAINTAINERS: Update email addresses for Chrysostomos Nanakos Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 43/44] MAINTAINERS: Add migration/block* to block subsystem Stefan Hajnoczi
2015-01-12 16:40 ` [Qemu-devel] [PULL v2 44/44] NVMe: Set correct VS Value for 1.1 Compliant Controllers Stefan Hajnoczi
2015-01-12 21:43 ` [Qemu-devel] [PULL v2 00/44] Block patches Peter Maydell
2015-01-13 13:19   ` Stefan Hajnoczi

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=1421080834-14724-32-git-send-email-stefanha@redhat.com \
    --to=stefanha@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --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).