Commit 7a7f4542 authored by Jean-Philippe Brucker's avatar Jean-Philippe Brucker Committed by Will Deacon
Browse files

threadpool: Add cancel() function



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: default avatarJean-Philippe Brucker <jean-philippe.brucker@arm.com>
Signed-off-by: default avatarJulien Thierry <julien.thierry@arm.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent 6730b51f
......@@ -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
......@@ -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);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment