This is an abstraction to support signalable threads. Signaling is inheritedly non-portable so this type of thread should only be used when absolutely necessary. I think the current users are the only users that should ever need to exist so strongly discourage future use.
Signed-off-by: Anthony Liguori <aligu...@us.ibm.com> diff --git a/cpu-defs.h b/cpu-defs.h index 9343824..ed2a209 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -203,7 +203,7 @@ typedef struct CPUWatchpoint { uint32_t created; \ uint32_t stop; /* Stop request */ \ uint32_t stopped; /* Artificially stopped */ \ - struct QemuThread *thread; \ + struct QemuSThread *thread; \ struct _GCond *halt_cond; \ struct qemu_work_item *queued_work_first, *queued_work_last; \ const char *cpu_model_str; \ diff --git a/cpus.c b/cpus.c index bc7363f..eebfe11 100644 --- a/cpus.c +++ b/cpus.c @@ -324,9 +324,9 @@ void vm_stop(int reason) GStaticMutex qemu_global_mutex; static GStaticMutex qemu_fair_mutex; -static QemuThread io_thread; +static QemuSThread io_thread; -static QemuThread *tcg_cpu_thread; +static QemuSThread *tcg_cpu_thread; static GCond *tcg_halt_cond; static int qemu_system_ready; @@ -420,7 +420,7 @@ int qemu_init_main_loop(void) g_static_mutex_init(&qemu_global_mutex); g_static_mutex_lock(&qemu_global_mutex); - qemu_thread_self(&io_thread); + qemu_sthread_self(&io_thread); return 0; } @@ -609,7 +609,7 @@ static void *kvm_cpu_thread_fn(void *arg) CPUState *env = arg; g_static_mutex_lock(&qemu_global_mutex); - qemu_thread_self(env->thread); + qemu_sthread_self(env->thread); if (kvm_enabled()) kvm_init_vcpu(env); @@ -642,7 +642,7 @@ static void *tcg_cpu_thread_fn(void *arg) CPUState *env = arg; tcg_init_ipi(); - qemu_thread_self(env->thread); + qemu_sthread_self(env->thread); /* signal CPU creation */ g_static_mutex_lock(&qemu_global_mutex); @@ -671,17 +671,17 @@ void qemu_cpu_kick(void *_env) { CPUState *env = _env; g_cond_broadcast(env->halt_cond); - qemu_thread_signal(env->thread, SIG_IPI); + qemu_sthread_signal(env->thread, SIG_IPI); } int qemu_cpu_self(void *_env) { CPUState *env = _env; - QemuThread this; + QemuSThread this; - qemu_thread_self(&this); + qemu_sthread_self(&this); - return qemu_thread_equal(&this, env->thread); + return qemu_sthread_equal(&this, env->thread); } static void cpu_signal(int sig) @@ -764,7 +764,7 @@ void qemu_mutex_lock_iothread(void) } else { g_static_mutex_lock(&qemu_fair_mutex); if (g_static_mutex_trylock(&qemu_global_mutex)) { - qemu_thread_signal(tcg_cpu_thread, SIG_IPI); + qemu_sthread_signal(tcg_cpu_thread, SIG_IPI); g_static_mutex_lock(&qemu_global_mutex); } g_static_mutex_unlock(&qemu_fair_mutex); @@ -830,9 +830,9 @@ static void tcg_init_vcpu(void *_env) CPUState *env = _env; /* share a single thread for all cpus with TCG */ if (!tcg_cpu_thread) { - env->thread = qemu_mallocz(sizeof(QemuThread)); + env->thread = qemu_mallocz(sizeof(QemuSThread)); env->halt_cond = g_cond_new(); - qemu_thread_create(env->thread, tcg_cpu_thread_fn, env); + qemu_sthread_create(env->thread, tcg_cpu_thread_fn, env); while (env->created == 0) { GTimeVal t; g_get_current_time(&t); @@ -850,9 +850,9 @@ static void tcg_init_vcpu(void *_env) static void kvm_start_vcpu(CPUState *env) { - env->thread = qemu_mallocz(sizeof(QemuThread)); + env->thread = qemu_mallocz(sizeof(QemuSThread)); env->halt_cond = g_cond_new(); - qemu_thread_create(env->thread, kvm_cpu_thread_fn, env); + qemu_sthread_create(env->thread, kvm_cpu_thread_fn, env); while (env->created == 0) { GTimeVal t; g_get_current_time(&t); @@ -887,10 +887,10 @@ static void qemu_system_vmstop_request(int reason) void vm_stop(int reason) { - QemuThread me; - qemu_thread_self(&me); + QemuSThread me; + qemu_sthread_self(&me); - if (!qemu_thread_equal(&me, &io_thread)) { + if (!qemu_sthread_equal(&me, &io_thread)) { qemu_system_vmstop_request(reason); /* * FIXME: should not return to device code in case diff --git a/qemu-thread.c b/qemu-thread.c index 6d0c51e..7ba4950 100644 --- a/qemu-thread.c +++ b/qemu-thread.c @@ -41,7 +41,7 @@ GThread *q_thread_create_nosignal(GThreadFunc func, struct trampoline_data { - QemuThread *thread; + QemuSThread *thread; void *(*startfn)(void *); void *opaque; GStaticMutex lock; @@ -61,7 +61,7 @@ static gpointer thread_trampoline(gpointer data) return retval; } -void qemu_thread_create(QemuThread *thread, +void qemu_sthread_create(QemuSThread *thread, void *(*start_routine)(void*), void *arg) { @@ -91,23 +91,23 @@ void qemu_thread_create(QemuThread *thread, g_static_mutex_free(&td->lock); } -void qemu_thread_signal(QemuThread *thread, int sig) +void qemu_sthread_signal(QemuSThread *thread, int sig) { pthread_kill(thread->tid, sig); } -void qemu_thread_self(QemuThread *thread) +void qemu_sthread_self(QemuSThread *thread) { thread->thread = g_thread_self(); thread->tid = pthread_self(); } -int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2) +int qemu_sthread_equal(QemuSThread *thread1, QemuSThread *thread2) { return (thread1->thread == thread2->thread); } -void qemu_thread_exit(void *retval) +void qemu_sthread_exit(void *retval) { g_thread_exit(retval); } diff --git a/qemu-thread.h b/qemu-thread.h index ec7fabd..a98a955 100644 --- a/qemu-thread.h +++ b/qemu-thread.h @@ -3,24 +3,38 @@ #include <glib.h> #include <pthread.h> -struct QemuThread { - GThread *thread; - pthread_t tid; -}; - -typedef struct QemuThread QemuThread; - +/** + * Light wrapper that sets signal mask appropriately for a non-I/O thread + */ GThread *q_thread_create_nosignal(GThreadFunc func, gpointer data, gboolean joinable, GError **error); -void qemu_thread_create(QemuThread *thread, - void *(*start_routine)(void*), - void *arg); -void qemu_thread_signal(QemuThread *thread, int sig); -void qemu_thread_self(QemuThread *thread); -int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2); -void qemu_thread_exit(void *retval); +/** + * Signal Threads + * + * Signal threads are non-portable types of threads that can be signaled + * directly. This is an interface that should disappear but requires that an + * appropriate abstraction be made. As of today, both TCG and KVM only support + * being interrupted via a signal so for platforms that don't support this, + * some other provisions must be made. + * + * Please do not use this interface in new code. Just use GThreads directly. + */ +struct QemuSThread { + GThread *thread; + pthread_t tid; +}; + +typedef struct QemuSThread QemuSThread; + +void qemu_sthread_create(QemuSThread *thread, + void *(*start_routine)(void*), + void *arg); +void qemu_sthread_signal(QemuSThread *thread, int sig); +void qemu_sthread_self(QemuSThread *thread); +int qemu_sthread_equal(QemuSThread *thread1, QemuSThread *thread2); +void qemu_sthread_exit(void *retval); #endif -- 1.7.0.4