2009-01-15 19:56:05 +00:00
/*
2012-12-13 15:49:48 +00:00
* virthreadpthread . c : basic thread synchronization primitives
2009-01-15 19:56:05 +00:00
*
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>
2013-05-02 14:23:02 -06:00
* Copyright ( C ) 2009 - 2011 , 2013 Red Hat , Inc .
2009-01-15 19:56:05 +00:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
2012-09-20 16:30:55 -06:00
* License along with this library . If not , see
2012-07-21 18:06:23 +08:00
* < http : //www.gnu.org/licenses/>.
2009-01-15 19:56:05 +00:00
*
*/
# include <config.h>
2010-11-18 13:03:56 +00:00
# include <unistd.h>
2010-12-04 14:33:23 -07:00
# include <inttypes.h>
2010-11-18 13:03:56 +00:00
# if HAVE_SYS_SYSCALL_H
# include <sys / syscall.h>
# endif
2012-12-12 18:06:53 +00:00
# include "viralloc.h"
2010-12-01 11:23:07 +00:00
2009-01-15 19:56:05 +00:00
/* Nothing special required for pthreads */
int virThreadInitialize ( void )
{
return 0 ;
}
void virThreadOnExit ( void )
{
}
2011-04-20 16:26:00 -06:00
int virOnce ( virOnceControlPtr once , virOnceFunc init )
{
return pthread_once ( & once - > once , init ) ;
}
2009-01-15 19:56:05 +00:00
int virMutexInit ( virMutexPtr m )
{
2009-10-28 19:54:07 +00:00
int ret ;
2010-03-18 11:32:16 -06:00
pthread_mutexattr_t attr ;
pthread_mutexattr_init ( & attr ) ;
pthread_mutexattr_settype ( & attr , PTHREAD_MUTEX_NORMAL ) ;
2010-12-15 14:12:30 +00:00
ret = pthread_mutex_init ( & m - > lock , & attr ) ;
pthread_mutexattr_destroy ( & attr ) ;
if ( ret ! = 0 ) {
2009-10-28 19:54:07 +00:00
errno = ret ;
2009-01-15 19:56:05 +00:00
return - 1 ;
}
return 0 ;
}
2010-03-25 13:45:59 -04:00
int virMutexInitRecursive ( virMutexPtr m )
{
int ret ;
pthread_mutexattr_t attr ;
pthread_mutexattr_init ( & attr ) ;
pthread_mutexattr_settype ( & attr , PTHREAD_MUTEX_RECURSIVE ) ;
2010-12-15 14:12:30 +00:00
ret = pthread_mutex_init ( & m - > lock , & attr ) ;
pthread_mutexattr_destroy ( & attr ) ;
if ( ret ! = 0 ) {
2010-03-25 13:45:59 -04:00
errno = ret ;
return - 1 ;
}
return 0 ;
}
2009-01-15 19:56:05 +00:00
void virMutexDestroy ( virMutexPtr m )
{
pthread_mutex_destroy ( & m - > lock ) ;
}
void virMutexLock ( virMutexPtr m ) {
pthread_mutex_lock ( & m - > lock ) ;
}
void virMutexUnlock ( virMutexPtr m )
{
pthread_mutex_unlock ( & m - > lock ) ;
}
int virCondInit ( virCondPtr c )
{
2009-10-28 19:54:07 +00:00
int ret ;
if ( ( ret = pthread_cond_init ( & c - > cond , NULL ) ) ! = 0 ) {
errno = ret ;
2009-01-15 19:56:05 +00:00
return - 1 ;
}
return 0 ;
}
int virCondDestroy ( virCondPtr c )
{
2009-10-28 19:54:07 +00:00
int ret ;
if ( ( ret = pthread_cond_destroy ( & c - > cond ) ) ! = 0 ) {
errno = ret ;
2009-01-15 19:56:05 +00:00
return - 1 ;
}
return 0 ;
}
int virCondWait ( virCondPtr c , virMutexPtr m )
{
2009-10-28 19:54:07 +00:00
int ret ;
if ( ( ret = pthread_cond_wait ( & c - > cond , & m - > lock ) ) ! = 0 ) {
errno = ret ;
2009-01-15 19:56:05 +00:00
return - 1 ;
}
return 0 ;
}
2009-11-03 13:40:15 -05:00
int virCondWaitUntil ( virCondPtr c , virMutexPtr m , unsigned long long whenms )
{
int ret ;
struct timespec ts ;
ts . tv_sec = whenms / 1000 ;
ts . tv_nsec = ( whenms % 1000 ) * 1000 ;
if ( ( ret = pthread_cond_timedwait ( & c - > cond , & m - > lock , & ts ) ) ! = 0 ) {
errno = ret ;
return - 1 ;
}
return 0 ;
}
2009-01-15 19:56:05 +00:00
void virCondSignal ( virCondPtr c )
{
pthread_cond_signal ( & c - > cond ) ;
}
void virCondBroadcast ( virCondPtr c )
{
pthread_cond_broadcast ( & c - > cond ) ;
}
2010-11-02 17:17:47 +00:00
struct virThreadArgs {
virThreadFunc func ;
void * opaque ;
} ;
static void * virThreadHelper ( void * data )
{
struct virThreadArgs * args = data ;
2011-12-20 15:06:47 -07:00
struct virThreadArgs local = * args ;
/* Free args early, rather than tying it up during the entire thread. */
2010-12-01 11:23:07 +00:00
VIR_FREE ( args ) ;
2011-12-20 15:06:47 -07:00
local . func ( local . opaque ) ;
2010-11-02 17:17:47 +00:00
return NULL ;
}
int virThreadCreate ( virThreadPtr thread ,
bool joinable ,
virThreadFunc func ,
void * opaque )
{
2010-12-01 11:23:07 +00:00
struct virThreadArgs * args ;
2010-11-02 17:17:47 +00:00
pthread_attr_t attr ;
2010-12-10 17:35:58 -07:00
int ret = - 1 ;
int err ;
if ( ( err = pthread_attr_init ( & attr ) ) ! = 0 )
goto cleanup ;
2013-06-07 10:37:25 +02:00
if ( VIR_ALLOC_QUIET ( args ) < 0 ) {
2010-12-10 17:35:58 -07:00
err = ENOMEM ;
goto cleanup ;
}
2010-12-01 11:23:07 +00:00
args - > func = func ;
args - > opaque = opaque ;
2010-11-02 17:17:47 +00:00
if ( ! joinable )
pthread_attr_setdetachstate ( & attr , 1 ) ;
2010-12-10 17:35:58 -07:00
err = pthread_create ( & thread - > thread , & attr , virThreadHelper , args ) ;
if ( err ! = 0 ) {
2010-12-01 11:23:07 +00:00
VIR_FREE ( args ) ;
2010-12-10 17:35:58 -07:00
goto cleanup ;
2010-11-02 17:17:47 +00:00
}
2010-12-01 11:23:07 +00:00
/* New thread owns 'args' in success case, so don't free */
2010-12-10 17:35:58 -07:00
ret = 0 ;
cleanup :
pthread_attr_destroy ( & attr ) ;
if ( ret < 0 )
errno = err ;
return ret ;
2010-11-02 17:17:47 +00:00
}
void virThreadSelf ( virThreadPtr thread )
{
thread - > thread = pthread_self ( ) ;
}
bool virThreadIsSelf ( virThreadPtr thread )
{
return pthread_equal ( pthread_self ( ) , thread - > thread ) ? true : false ;
}
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>
2013-05-02 14:23:02 -06:00
/* 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 virThreadSelfID ( void )
2010-11-18 13:03:56 +00:00
{
# if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid)
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>
2013-05-02 14:23:02 -06:00
pid_t tid = syscall ( SYS_gettid ) ;
return tid ;
2010-11-18 13:03:56 +00:00
# else
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>
2013-05-02 14:23:02 -06:00
union {
unsigned long long l ;
pthread_t t ;
} u ;
u . t = pthread_self ( ) ;
return u . l ;
2010-11-18 13:03:56 +00:00
# endif
}
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>
2013-05-02 14:23:02 -06:00
/* 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 virThreadID ( virThreadPtr thread )
2010-12-04 14:33:23 -07:00
{
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>
2013-05-02 14:23:02 -06:00
union {
unsigned long long l ;
pthread_t t ;
} u ;
u . t = thread - > thread ;
return u . l ;
2010-12-04 14:33:23 -07:00
}
2010-11-02 17:17:47 +00:00
void virThreadJoin ( virThreadPtr thread )
{
pthread_join ( thread - > thread , NULL ) ;
}
2009-01-15 19:56:05 +00:00
2012-01-23 14:58:13 +00:00
void virThreadCancel ( virThreadPtr thread )
{
pthread_cancel ( thread - > thread ) ;
}
2009-01-15 19:56:05 +00:00
int virThreadLocalInit ( virThreadLocalPtr l ,
virThreadLocalCleanup c )
{
2009-10-28 19:54:07 +00:00
int ret ;
if ( ( ret = pthread_key_create ( & l - > key , c ) ) ! = 0 ) {
errno = ret ;
2009-01-15 19:56:05 +00:00
return - 1 ;
}
return 0 ;
}
void * virThreadLocalGet ( virThreadLocalPtr l )
{
return pthread_getspecific ( l - > key ) ;
}
2011-12-20 15:06:47 -07:00
int virThreadLocalSet ( virThreadLocalPtr l , void * val )
2009-01-15 19:56:05 +00:00
{
2011-12-20 15:06:47 -07:00
int err = pthread_setspecific ( l - > key , val ) ;
if ( err ) {
errno = err ;
return - 1 ;
}
return 0 ;
2009-01-15 19:56:05 +00:00
}