From 956953884e1ba475b02e4b7d8311680c0ec4f83b Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Mon, 8 Jul 2013 12:27:34 +0200 Subject: [PATCH] Add support for tracking thread jobs Each thread can use a thread local variable to keep the name of a job which is currently running in the job. The virThreadJobSetWorker API is supposed to be called once by any thread which is used as a worker, i.e., it is waiting in a pool, woken up to do a job, and returned back to the pool. The virThreadJobSet/virThreadJobClear APIs are to be called at the beginning/end of each job. Signed-off-by: Jiri Denemark --- include/libvirt/virterror.h | 1 + po/POTFILES.in | 1 + src/Makefile.am | 2 + src/libvirt_private.syms | 7 ++ src/util/virerror.c | 1 + src/util/virthreadjob.c | 126 ++++++++++++++++++++++++++++++++++++ src/util/virthreadjob.h | 33 ++++++++++ 7 files changed, 171 insertions(+) create mode 100644 src/util/virthreadjob.c create mode 100644 src/util/virthreadjob.h diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 5dc99dc1bd..9c5b069282 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -125,6 +125,7 @@ typedef enum { VIR_FROM_FIREWALL = 59, /* Error from firewall */ VIR_FROM_POLKIT = 60, /* Error from polkit code */ + VIR_FROM_THREAD = 61, /* Error from thread utils */ # ifdef VIR_ENUM_SENTINELS VIR_ERR_DOMAIN_LAST diff --git a/po/POTFILES.in b/po/POTFILES.in index ab6ae3bf23..dd06ab3c52 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -220,6 +220,7 @@ src/util/virstorageencryption.c src/util/virstoragefile.c src/util/virstring.c src/util/virsysinfo.c +src/util/virthreadjob.c src/util/virtime.c src/util/virtpm.c src/util/virtypedparam.c diff --git a/src/Makefile.am b/src/Makefile.am index 00b47e78a7..ec62ab4607 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -160,6 +160,7 @@ UTIL_SOURCES = \ util/virsysinfo.c util/virsysinfo.h \ util/virsystemd.c util/virsystemd.h \ util/virthread.c util/virthread.h \ + util/virthreadjob.c utils/virthreadjob.h \ util/virthreadpool.c util/virthreadpool.h \ util/virtime.h util/virtime.c \ util/virtpm.h util/virtpm.c \ @@ -2147,6 +2148,7 @@ libvirt_setuid_rpc_client_la_SOURCES = \ util/virstring.c \ util/virtime.c \ util/virthread.c \ + util/virthreadjob.c \ util/virtypedparam.c \ util/viruri.c \ util/virutil.c \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 33222f075e..a8dced5cdc 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2190,6 +2190,13 @@ virThreadSelf; virThreadSelfID; +# util/virthreadjob.h +virThreadJobClear; +virThreadJobGet; +virThreadJobSet; +virThreadJobSetWorker; + + # util/virthreadpool.h virThreadPoolFree; virThreadPoolGetMaxWorkers; diff --git a/src/util/virerror.c b/src/util/virerror.c index 9635c8212f..c4e84e73cd 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -132,6 +132,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST, "Firewall", "Polkit", /* 60 */ + "Thread jobs", ) diff --git a/src/util/virthreadjob.c b/src/util/virthreadjob.c new file mode 100644 index 0000000000..2f483f9d26 --- /dev/null +++ b/src/util/virthreadjob.c @@ -0,0 +1,126 @@ +/* + * virthreadjob.c: code for tracking job associated with current thread + * + * Copyright (C) 2013-2015 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 + * 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 + * License along with this library. If not, see + * . + * + * Author: Jiri Denemark + */ + +#include + +#include "internal.h" +#include "virerror.h" +#include "virlog.h" +#include "virthread.h" +#include "virthreadjob.h" + +#define VIR_FROM_THIS VIR_FROM_THREAD +VIR_LOG_INIT("util.threadjob"); + +virThreadLocal virThreadJobWorker; +virThreadLocal virThreadJobName; + + +static int +virThreadJobOnceInit(void) +{ + if (virThreadLocalInit(&virThreadJobWorker, NULL) < 0 || + virThreadLocalInit(&virThreadJobName, NULL) < 0) + return -1; + return 0; +} + +VIR_ONCE_GLOBAL_INIT(virThreadJob) + + +const char * +virThreadJobGet(void) +{ + const char *job; + + if (virThreadJobInitialize() < 0) + return NULL; + + job = virThreadLocalGet(&virThreadJobName); + if (!job) + job = virThreadLocalGet(&virThreadJobWorker); + + return job; +} + + +void +virThreadJobSetWorker(const char *worker) +{ + if (!worker || virThreadJobInitialize() < 0) + return; + + if (virThreadLocalSet(&virThreadJobWorker, (void *) worker) < 0) + virReportSystemError(errno, + _("cannot set worker name to %s"), + worker); + + VIR_DEBUG("Thread %llu is running worker %s", virThreadSelfID(), worker); +} + + +void +virThreadJobSet(const char *caller) +{ + const char *worker; + + if (!caller || virThreadJobInitialize() < 0) + return; + + if (virThreadLocalSet(&virThreadJobName, (void *) caller) < 0) + virReportSystemError(errno, + _("cannot set current job to %s"), + caller); + + if ((worker = virThreadLocalGet(&virThreadJobWorker))) { + VIR_DEBUG("Thread %llu (%s) is now running job %s", + virThreadSelfID(), worker, caller); + } else { + VIR_DEBUG("Thread %llu is now running job %s", + virThreadSelfID(), caller); + } +} + + +void +virThreadJobClear(int rv) +{ + const char *old; + const char *worker; + + if (virThreadJobInitialize() < 0) + return; + + if (!(old = virThreadLocalGet(&virThreadJobName))) + return; + + if (virThreadLocalSet(&virThreadJobName, NULL) < 0) + virReportSystemError(errno, "%s", _("cannot reset current job")); + + if ((worker = virThreadLocalGet(&virThreadJobWorker))) { + VIR_DEBUG("Thread %llu (%s) finished job %s with ret=%d", + virThreadSelfID(), worker, old, rv); + } else { + VIR_DEBUG("Thread %llu finished job %s with ret=%d", + virThreadSelfID(), old, rv); + } +} diff --git a/src/util/virthreadjob.h b/src/util/virthreadjob.h new file mode 100644 index 0000000000..659f91db43 --- /dev/null +++ b/src/util/virthreadjob.h @@ -0,0 +1,33 @@ +/* + * virthreadjob.h: APIs for tracking job associated with current thread + * + * Copyright (C) 2013-2015 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 + * 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 + * License along with this library. If not, see + * . + * + * Author: Jiri Denemark + */ + +#ifndef __VIR_THREAD_JOB_H__ +# define __VIR_THREAD_JOB_H__ + + +const char *virThreadJobGet(void); + +void virThreadJobSetWorker(const char *caller); +void virThreadJobSet(const char *caller); +void virThreadJobClear(int rv); + +#endif -- GitLab