build: avoid non-portable cast of pthread_t

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 scalar pthread_t to void* triggers a different
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.

* 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@redhat.com>
This commit is contained in:
Eric Blake 2013-05-02 14:23:02 -06:00
parent 9eafa25116
commit 22d12905e6
7 changed files with 45 additions and 35 deletions

View File

@ -187,7 +187,7 @@ qemuDomainObjTransferJob(virDomainObjPtr obj)
{ {
qemuDomainObjPrivatePtr priv = obj->privateData; qemuDomainObjPrivatePtr priv = obj->privateData;
VIR_DEBUG("Changing job owner from %d to %d", VIR_DEBUG("Changing job owner from %llu to %llu",
priv->job.owner, virThreadSelfID()); priv->job.owner, virThreadSelfID());
priv->job.owner = virThreadSelfID(); priv->job.owner = virThreadSelfID();
} }
@ -846,7 +846,7 @@ qemuDomainObjSetJobPhase(virQEMUDriverPtr driver,
int phase) int phase)
{ {
qemuDomainObjPrivatePtr priv = obj->privateData; qemuDomainObjPrivatePtr priv = obj->privateData;
int me = virThreadSelfID(); unsigned long long me = virThreadSelfID();
if (!priv->job.asyncJob) if (!priv->job.asyncJob)
return; return;
@ -856,7 +856,7 @@ qemuDomainObjSetJobPhase(virQEMUDriverPtr driver,
qemuDomainAsyncJobPhaseToString(priv->job.asyncJob, phase)); qemuDomainAsyncJobPhaseToString(priv->job.asyncJob, phase));
if (priv->job.asyncOwner && me != priv->job.asyncOwner) { 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 %llu",
qemuDomainAsyncJobTypeToString(priv->job.asyncJob), qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
priv->job.asyncOwner); priv->job.asyncOwner);
} }
@ -898,7 +898,7 @@ qemuDomainObjReleaseAsyncJob(virDomainObjPtr obj)
qemuDomainAsyncJobTypeToString(priv->job.asyncJob)); qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
if (priv->job.asyncOwner != virThreadSelfID()) { if (priv->job.asyncOwner != virThreadSelfID()) {
VIR_WARN("'%s' async job is owned by thread %d", VIR_WARN("'%s' async job is owned by thread %llu",
qemuDomainAsyncJobTypeToString(priv->job.asyncJob), qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
priv->job.asyncOwner); priv->job.asyncOwner);
} }
@ -992,7 +992,7 @@ retry:
error: error:
VIR_WARN("Cannot start job (%s, %s) for domain %s;" 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 (%llu, %llu)",
qemuDomainJobTypeToString(job), qemuDomainJobTypeToString(job),
qemuDomainAsyncJobTypeToString(asyncJob), qemuDomainAsyncJobTypeToString(asyncJob),
obj->def->name, obj->def->name,
@ -1056,7 +1056,7 @@ qemuDomainObjBeginNestedJob(virQEMUDriverPtr driver,
} }
if (priv->job.asyncOwner != virThreadSelfID()) { 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: %llu",
priv->job.asyncOwner); priv->job.asyncOwner);
} }

View File

@ -102,11 +102,11 @@ VIR_ENUM_DECL(qemuDomainAsyncJob)
struct qemuDomainJobObj { struct qemuDomainJobObj {
virCond cond; /* Use to coordinate jobs */ virCond cond; /* Use to coordinate jobs */
enum qemuDomainJob active; /* Currently running job */ enum qemuDomainJob active; /* Currently running job */
int owner; /* Thread which set current job */ unsigned long long owner; /* Thread id which set current job */
virCond asyncCond; /* Use to coordinate with async jobs */ virCond asyncCond; /* Use to coordinate with async jobs */
enum qemuDomainAsyncJob asyncJob; /* Currently active async job */ enum qemuDomainAsyncJob asyncJob; /* Currently active async job */
int asyncOwner; /* Thread which set current async job */ unsigned long long asyncOwner; /* Thread which set current async job */
int phase; /* Job phase (mainly for migrations) */ int phase; /* Job phase (mainly for migrations) */
unsigned long long mask; /* Jobs allowed during async job */ unsigned long long mask; /* Jobs allowed during async job */
unsigned long long start; /* When the async job started */ unsigned long long start; /* When the async job started */

View File

@ -1,7 +1,7 @@
/* /*
* vireventpoll.c: Poll based event loop for monitoring file handles * 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 * Copyright (C) 2007 Daniel P. Berrange
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
@ -708,7 +708,7 @@ static int virEventPollInterruptLocked(void)
if (!eventLoop.running || if (!eventLoop.running ||
virThreadIsSelf(&eventLoop.leader)) { virThreadIsSelf(&eventLoop.leader)) {
VIR_DEBUG("Skip interrupt, %d %d", eventLoop.running, VIR_DEBUG("Skip interrupt, %d %llu", eventLoop.running,
virThreadID(&eventLoop.leader)); virThreadID(&eventLoop.leader));
return 0; return 0;
} }

View File

@ -1,7 +1,7 @@
/* /*
* virlog.c: internal logging and debugging * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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. * to just grep for it to find the right place.
*/ */
if ((funcname != NULL)) { if ((funcname != NULL)) {
ret = virAsprintf(msg, "%d: %s : %s:%d : %s\n", ret = virAsprintf(msg, "%llu: %s : %s:%d : %s\n",
virThreadSelfID(), virLogPriorityString(priority), virThreadSelfID(), virLogPriorityString(priority),
funcname, linenr, str); funcname, linenr, str);
} else { } else {
ret = virAsprintf(msg, "%d: %s : %s\n", ret = virAsprintf(msg, "%llu: %s : %s\n",
virThreadSelfID(), virLogPriorityString(priority), virThreadSelfID(), virLogPriorityString(priority),
str); str);
} }

View File

@ -1,7 +1,7 @@
/* /*
* virthread.h: basic thread synchronization primitives * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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 * guaranteed to give unique values for distinct threads on all
* architectures, nor are the two functions guaranteed to give the same * architectures, nor are the two functions guaranteed to give the same
* value for the same thread. */ * value for the same thread. */
int virThreadSelfID(void); unsigned long long virThreadSelfID(void);
int virThreadID(virThreadPtr thread); unsigned long long virThreadID(virThreadPtr thread);
/* Static initialization of mutexes is not possible, so we instead /* Static initialization of mutexes is not possible, so we instead
* provide for guaranteed one-time initialization via a callback * provide for guaranteed one-time initialization via a callback

View File

@ -1,7 +1,7 @@
/* /*
* virthreadpthread.c: basic thread synchronization primitives * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -210,25 +210,35 @@ bool virThreadIsSelf(virThreadPtr thread)
return pthread_equal(pthread_self(), thread->thread) ? true : false; return pthread_equal(pthread_self(), thread->thread) ? true : false;
} }
/* For debugging use only; this result is not guaranteed unique on BSD /* For debugging use only; this result is not guaranteed unique if
* systems when pthread_t is a 64-bit pointer. */ * pthread_t is larger than a 64-bit pointer, nor does it always match
int virThreadSelfID(void) * the pthread_self() id on Linux. */
unsigned long long virThreadSelfID(void)
{ {
#if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid) #if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid)
pid_t tid; pid_t tid = syscall(SYS_gettid);
tid = syscall(SYS_gettid); return tid;
return (int)tid;
#else #else
return (int)(intptr_t)(void *)pthread_self(); union {
unsigned long long l;
pthread_t t;
} u;
u.t = pthread_self();
return u.l;
#endif #endif
} }
/* For debugging use only; this result is not guaranteed unique on BSD /* For debugging use only; this result is not guaranteed unique if
* systems when pthread_t is a 64-bit pointer, nor does it match the * pthread_t is larger than a 64-bit pointer, nor does it always match
* thread id of virThreadSelfID on Linux. */ * the thread id of virThreadSelfID on Linux. */
int virThreadID(virThreadPtr thread) unsigned long long virThreadID(virThreadPtr thread)
{ {
return (int)(uintptr_t)thread->thread; union {
unsigned long long l;
pthread_t t;
} u;
u.t = thread->thread;
return u.l;
} }
void virThreadJoin(virThreadPtr thread) void virThreadJoin(virThreadPtr thread)

View File

@ -1,7 +1,7 @@
/* /*
* virthreadwin32.c: basic thread synchronization primitives * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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; return self.thread == thread->thread ? true : false;
} }
/* For debugging use only; see comments in threads-pthread.c. */ /* For debugging use only; see comments in virthreadpthread.c. */
int virThreadSelfID(void) unsigned long long virThreadSelfID(void)
{ {
return (int)GetCurrentThreadId(); return GetCurrentThreadId();
} }
/* For debugging use only; see comments in threads-pthread.c. */ /* For debugging use only; see comments in virthreadpthread.c. */
int virThreadID(virThreadPtr thread) unsigned long long virThreadID(virThreadPtr thread)
{ {
return (intptr_t)thread->thread; return (intptr_t)thread->thread;
} }