From patchwork Tue Dec 4 11:08:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Thierry X-Patchwork-Id: 10711517 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C29AD13AF for ; Tue, 4 Dec 2018 11:11:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B31002B100 for ; Tue, 4 Dec 2018 11:11:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A74962B139; Tue, 4 Dec 2018 11:11:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 33E9E2B100 for ; Tue, 4 Dec 2018 11:11:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728414AbeLDLLJ (ORCPT ); Tue, 4 Dec 2018 06:11:09 -0500 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]:57392 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728248AbeLDLJG (ORCPT ); Tue, 4 Dec 2018 06:09:06 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id F36BA15BE; Tue, 4 Dec 2018 03:09:05 -0800 (PST) Received: from e112298-lin.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id DAF453F5AF; Tue, 4 Dec 2018 03:09:04 -0800 (PST) From: Julien Thierry To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: jean-philippe.brucker@arm.com, will.deacon@arm.com, Julien Thierry Subject: [PATCH kvmtool 11/13] threadpool: Add cancel() function Date: Tue, 4 Dec 2018 11:08:44 +0000 Message-Id: <1543921726-54571-12-git-send-email-julien.thierry@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1543921726-54571-1-git-send-email-julien.thierry@arm.com> References: <1543921726-54571-1-git-send-email-julien.thierry@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Jean-Philippe Brucker When resetting a virtqueue, it is often necessary to make sure that the associated threadpool job isn't running anymore. Add a function to cancel a job. A threadpool job has three states: idle, queued and running. A job is queued when it is in the job list. It is running when it is out the list, but its signal count is greater than zero. It is idle when it is both out of the list and its signal count is zero. The cancel() function simply waits for the job to be idle. It is up to the caller to make sure that the job isn't queued concurrently. Signed-off-by: Jean-Philippe Brucker Signed-off-by: Julien Thierry --- include/kvm/threadpool.h | 2 ++ util/threadpool.c | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/kvm/threadpool.h b/include/kvm/threadpool.h index bacb243..880487a 100644 --- a/include/kvm/threadpool.h +++ b/include/kvm/threadpool.h @@ -28,11 +28,13 @@ static inline void thread_pool__init_job(struct thread_pool__job *job, struct kv .data = data, .mutex = MUTEX_INITIALIZER, }; + INIT_LIST_HEAD(&job->queue); } int thread_pool__init(struct kvm *kvm); int thread_pool__exit(struct kvm *kvm); void thread_pool__do_job(struct thread_pool__job *job); +void thread_pool__cancel_job(struct thread_pool__job *job); #endif diff --git a/util/threadpool.c b/util/threadpool.c index e64aa26..1dc3bf7 100644 --- a/util/threadpool.c +++ b/util/threadpool.c @@ -25,7 +25,7 @@ static struct thread_pool__job *thread_pool__job_pop_locked(void) return NULL; job = list_first_entry(&head, struct thread_pool__job, queue); - list_del(&job->queue); + list_del_init(&job->queue); return job; } @@ -173,3 +173,26 @@ void thread_pool__do_job(struct thread_pool__job *job) pthread_cond_signal(&job_cond); mutex_unlock(&job_mutex); } + +void thread_pool__cancel_job(struct thread_pool__job *job) +{ + bool running; + + /* + * If the job is queued but not running, remove it. Otherwise, wait for + * the signalcount to drop to 0, indicating that it has finished + * running. We assume that nobody is queueing this job - + * thread_pool__do_job() isn't called - while this function is running. + */ + do { + mutex_lock(&job_mutex); + if (list_empty(&job->queue)) { + running = job->signalcount > 0; + } else { + list_del_init(&job->queue); + job->signalcount = 0; + running = false; + } + mutex_unlock(&job_mutex); + } while (running); +}