[libvirt] [PATCH] build: avoid non-portable cast of pthread_t
Guido Günther
agx at sigxcpu.org
Fri May 3 06:19:01 UTC 2013
Hi Eric,
On Thu, May 02, 2013 at 03:58:23PM -0600, Eric Blake wrote:
> POSIX says pthread_t is opaque. We can't guarantee if it is scaler
> or a pointer, nor what size it is; and BSD differs from Linux.
> We've also had reports of gcc complaining on attempts to cast it,
> if we use a cast to the wrong type (for example, pointers have to be
> cast to void* or intptr_t before being narrowed; while casting a
> function return of pthread_t to void* triggers another warning).
>
> Give up on casts, and use unions to get at decent bits instead. And
> rather than futz around with figuring which 32 bits of a potentially
> 64-bit pointer are most likely to be unique, convert the rest of
> the code base to use 64-bit values when using a debug id.
>
> Based on a report by Guido Günther against kFreeBSD, but with a
> fix that doesn't regress commit 4d970fd29 for FreeBSD.
Works on kFreeBSD here, thanks.
-- Guido
>
> * src/util/virthreadpthread.c (virThreadSelfID, virThreadID): Use
> union to get at a decent bit representation of thread_t bits.
> * src/util/virthread.h (virThreadSelfID, virThreadID): Alter
> signature.
> * src/util/virthreadwin32.c (virThreadSelfID, virThreadID):
> Likewise.
> * src/qemu/qemu_domain.h (qemuDomainJobObj): Alter type of owner.
> * src/qemu/qemu_domain.c (qemuDomainObjTransferJob)
> (qemuDomainObjSetJobPhase, qemuDomainObjReleaseAsyncJob)
> (qemuDomainObjBeginNestedJob, qemuDomainObjBeginJobInternal): Fix
> clients.
> * src/util/virlog.c (virLogFormatString): Likewise.
> * src/util/vireventpoll.c (virEventPollInterruptLocked):
> Likewise.
>
> Signed-off-by: Eric Blake <eblake at redhat.com>
> ---
>
> This one needs a review.
>
> I've tested this on Fedora 18 and FreeBSD 8.2; I also ran it through
> the mingw64 cross-compiler on Fedora (thanks to autobuild.sh), without
> grief. But I don't have a kFreeBSD system handy, which was the
> original source of the compilation complaint.
>
> src/qemu/qemu_domain.c | 12 ++++++------
> src/qemu/qemu_domain.h | 4 ++--
> src/util/vireventpoll.c | 4 ++--
> src/util/virlog.c | 6 +++---
> src/util/virthread.h | 6 +++---
> src/util/virthreadpthread.c | 33 ++++++++++++++++++++++-----------
> src/util/virthreadwin32.c | 12 ++++++------
> 7 files changed, 44 insertions(+), 33 deletions(-)
>
> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> index 47edfba..bfc57e5 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -187,7 +187,7 @@ qemuDomainObjTransferJob(virDomainObjPtr obj)
> {
> qemuDomainObjPrivatePtr priv = obj->privateData;
>
> - VIR_DEBUG("Changing job owner from %d to %d",
> + VIR_DEBUG("Changing job owner from %lld to %lld",
> priv->job.owner, virThreadSelfID());
> priv->job.owner = virThreadSelfID();
> }
> @@ -846,7 +846,7 @@ qemuDomainObjSetJobPhase(virQEMUDriverPtr driver,
> int phase)
> {
> qemuDomainObjPrivatePtr priv = obj->privateData;
> - int me = virThreadSelfID();
> + unsigned long long int me = virThreadSelfID();
>
> if (!priv->job.asyncJob)
> return;
> @@ -856,7 +856,7 @@ qemuDomainObjSetJobPhase(virQEMUDriverPtr driver,
> qemuDomainAsyncJobPhaseToString(priv->job.asyncJob, phase));
>
> if (priv->job.asyncOwner && me != priv->job.asyncOwner) {
> - VIR_WARN("'%s' async job is owned by thread %d",
> + VIR_WARN("'%s' async job is owned by thread %lld",
> qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
> priv->job.asyncOwner);
> }
> @@ -898,7 +898,7 @@ qemuDomainObjReleaseAsyncJob(virDomainObjPtr obj)
> qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
>
> if (priv->job.asyncOwner != virThreadSelfID()) {
> - VIR_WARN("'%s' async job is owned by thread %d",
> + VIR_WARN("'%s' async job is owned by thread %lld",
> qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
> priv->job.asyncOwner);
> }
> @@ -992,7 +992,7 @@ retry:
>
> error:
> VIR_WARN("Cannot start job (%s, %s) for domain %s;"
> - " current job is (%s, %s) owned by (%d, %d)",
> + " current job is (%s, %s) owned by (%lld, %lld)",
> qemuDomainJobTypeToString(job),
> qemuDomainAsyncJobTypeToString(asyncJob),
> obj->def->name,
> @@ -1056,7 +1056,7 @@ qemuDomainObjBeginNestedJob(virQEMUDriverPtr driver,
> }
>
> if (priv->job.asyncOwner != virThreadSelfID()) {
> - VIR_WARN("This thread doesn't seem to be the async job owner: %d",
> + VIR_WARN("This thread doesn't seem to be the async job owner: %lld",
> priv->job.asyncOwner);
> }
>
> diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
> index da04377..7746ba9 100644
> --- a/src/qemu/qemu_domain.h
> +++ b/src/qemu/qemu_domain.h
> @@ -102,11 +102,11 @@ VIR_ENUM_DECL(qemuDomainAsyncJob)
> struct qemuDomainJobObj {
> virCond cond; /* Use to coordinate jobs */
> enum qemuDomainJob active; /* Currently running job */
> - int owner; /* Thread which set current job */
> + unsigned long long int owner; /* Thread id which set current job */
>
> virCond asyncCond; /* Use to coordinate with async jobs */
> enum qemuDomainAsyncJob asyncJob; /* Currently active async job */
> - int asyncOwner; /* Thread which set current async job */
> + unsigned long long int asyncOwner; /* Thread which set current async job */
> int phase; /* Job phase (mainly for migrations) */
> unsigned long long mask; /* Jobs allowed during async job */
> unsigned long long start; /* When the async job started */
> diff --git a/src/util/vireventpoll.c b/src/util/vireventpoll.c
> index 5c6d31b..19add73 100644
> --- a/src/util/vireventpoll.c
> +++ b/src/util/vireventpoll.c
> @@ -1,7 +1,7 @@
> /*
> * vireventpoll.c: Poll based event loop for monitoring file handles
> *
> - * Copyright (C) 2007, 2010-2012 Red Hat, Inc.
> + * Copyright (C) 2007, 2010-2013 Red Hat, Inc.
> * Copyright (C) 2007 Daniel P. Berrange
> *
> * This library is free software; you can redistribute it and/or
> @@ -708,7 +708,7 @@ static int virEventPollInterruptLocked(void)
>
> if (!eventLoop.running ||
> virThreadIsSelf(&eventLoop.leader)) {
> - VIR_DEBUG("Skip interrupt, %d %d", eventLoop.running,
> + VIR_DEBUG("Skip interrupt, %d %lld", eventLoop.running,
> virThreadID(&eventLoop.leader));
> return 0;
> }
> diff --git a/src/util/virlog.c b/src/util/virlog.c
> index bd47b38..b2e6458 100644
> --- a/src/util/virlog.c
> +++ b/src/util/virlog.c
> @@ -1,7 +1,7 @@
> /*
> * virlog.c: internal logging and debugging
> *
> - * Copyright (C) 2008, 2010-2012 Red Hat, Inc.
> + * Copyright (C) 2008, 2010-2013 Red Hat, Inc.
> *
> * This library is free software; you can redistribute it and/or
> * modify it under the terms of the GNU Lesser General Public
> @@ -708,11 +708,11 @@ virLogFormatString(char **msg,
> * to just grep for it to find the right place.
> */
> if ((funcname != NULL)) {
> - ret = virAsprintf(msg, "%d: %s : %s:%d : %s\n",
> + ret = virAsprintf(msg, "%lld: %s : %s:%d : %s\n",
> virThreadSelfID(), virLogPriorityString(priority),
> funcname, linenr, str);
> } else {
> - ret = virAsprintf(msg, "%d: %s : %s\n",
> + ret = virAsprintf(msg, "%lld: %s : %s\n",
> virThreadSelfID(), virLogPriorityString(priority),
> str);
> }
> diff --git a/src/util/virthread.h b/src/util/virthread.h
> index ca1306a..447fe84 100644
> --- a/src/util/virthread.h
> +++ b/src/util/virthread.h
> @@ -1,7 +1,7 @@
> /*
> * virthread.h: basic thread synchronization primitives
> *
> - * Copyright (C) 2009-2011 Red Hat, Inc.
> + * Copyright (C) 2009-2011, 2013 Red Hat, Inc.
> *
> * This library is free software; you can redistribute it and/or
> * modify it under the terms of the GNU Lesser General Public
> @@ -63,8 +63,8 @@ void virThreadCancel(virThreadPtr thread);
> * guaranteed to give unique values for distinct threads on all
> * architectures, nor are the two functions guaranteed to give the same
> * value for the same thread. */
> -int virThreadSelfID(void);
> -int virThreadID(virThreadPtr thread);
> +unsigned long long int virThreadSelfID(void);
> +unsigned long long int virThreadID(virThreadPtr thread);
>
> /* Static initialization of mutexes is not possible, so we instead
> * provide for guaranteed one-time initialization via a callback
> diff --git a/src/util/virthreadpthread.c b/src/util/virthreadpthread.c
> index b42b333..20fa539 100644
> --- a/src/util/virthreadpthread.c
> +++ b/src/util/virthreadpthread.c
> @@ -1,7 +1,7 @@
> /*
> * virthreadpthread.c: basic thread synchronization primitives
> *
> - * Copyright (C) 2009-2011 Red Hat, Inc.
> + * Copyright (C) 2009-2011, 2013 Red Hat, Inc.
> *
> * This library is free software; you can redistribute it and/or
> * modify it under the terms of the GNU Lesser General Public
> @@ -210,25 +210,36 @@ bool virThreadIsSelf(virThreadPtr thread)
> return pthread_equal(pthread_self(), thread->thread) ? true : false;
> }
>
> -/* For debugging use only; this result is not guaranteed unique on BSD
> - * systems when pthread_t is a 64-bit pointer. */
> -int virThreadSelfID(void)
> +/* For debugging use only; this result is not guaranteed unique if
> + * pthread_t is larger than a 64-bit pointer, nor does it always match
> + * the pthread_self() id on Linux. */
> +unsigned long long int virThreadSelfID(void)
> {
> #if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid)
> pid_t tid;
> tid = syscall(SYS_gettid);
> - return (int)tid;
> + return tid;
> #else
> - return (int)(intptr_t)(void *)pthread_self();
> + union {
> + unsigned long long int i;
> + pthread_t t;
> + } u;
> + u.t = pthread_self();
> + return u.i;
> #endif
> }
>
> -/* For debugging use only; this result is not guaranteed unique on BSD
> - * systems when pthread_t is a 64-bit pointer, nor does it match the
> - * thread id of virThreadSelfID on Linux. */
> -int virThreadID(virThreadPtr thread)
> +/* For debugging use only; this result is not guaranteed unique if
> + * pthread_t is larger than a 64-bit pointer, nor does it always match
> + * the thread id of virThreadSelfID on Linux. */
> +unsigned long long int virThreadID(virThreadPtr thread)
> {
> - return (int)(uintptr_t)thread->thread;
> + union {
> + unsigned long long int i;
> + pthread_t t;
> + } u;
> + u.t = thread->thread;
> + return u.i;
> }
>
> void virThreadJoin(virThreadPtr thread)
> diff --git a/src/util/virthreadwin32.c b/src/util/virthreadwin32.c
> index 4543ad8..10837d2 100644
> --- a/src/util/virthreadwin32.c
> +++ b/src/util/virthreadwin32.c
> @@ -1,7 +1,7 @@
> /*
> * virthreadwin32.c: basic thread synchronization primitives
> *
> - * Copyright (C) 2009-2011 Red Hat, Inc.
> + * Copyright (C) 2009-2011, 2013 Red Hat, Inc.
> *
> * This library is free software; you can redistribute it and/or
> * modify it under the terms of the GNU Lesser General Public
> @@ -334,14 +334,14 @@ bool virThreadIsSelf(virThreadPtr thread)
> return self.thread == thread->thread ? true : false;
> }
>
> -/* For debugging use only; see comments in threads-pthread.c. */
> -int virThreadSelfID(void)
> +/* For debugging use only; see comments in virthreadpthread.c. */
> +unsigned long long int virThreadSelfID(void)
> {
> - return (int)GetCurrentThreadId();
> + return GetCurrentThreadId();
> }
>
> -/* For debugging use only; see comments in threads-pthread.c. */
> -int virThreadID(virThreadPtr thread)
> +/* For debugging use only; see comments in virthreadpthread.c. */
> +unsigned long long int virThreadID(virThreadPtr thread)
> {
> return (intptr_t)thread->thread;
> }
> --
> 1.8.1.4
>
More information about the libvir-list
mailing list