aboutsummaryrefslogtreecommitdiff
path: root/job.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2018-04-18 16:32:20 +0200
committerKevin Wolf <kwolf@redhat.com>2018-05-23 14:30:50 +0200
commit5d43e86e11f488fda7956b13160e0c0105a84845 (patch)
treeb5c4200538b55bb476e92b197a352ea4e3c09ce0 /job.c
parentda01ff7f38f52791f93fc3ca59afcfbb220f15af (diff)
job: Add job_sleep_ns()
There is nothing block layer specific about block_job_sleep_ns(), so move the function to Job. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com>
Diffstat (limited to 'job.c')
-rw-r--r--job.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/job.c b/job.c
index 78497fd6f5..1b8cba15ff 100644
--- a/job.c
+++ b/job.c
@@ -152,6 +152,13 @@ Job *job_get(const char *id)
return NULL;
}
+static void job_sleep_timer_cb(void *opaque)
+{
+ Job *job = opaque;
+
+ job_enter(job);
+}
+
void *job_create(const char *job_id, const JobDriver *driver, AioContext *ctx,
Error **errp)
{
@@ -178,6 +185,9 @@ void *job_create(const char *job_id, const JobDriver *driver, AioContext *ctx,
job->pause_count = 1;
job_state_transition(job, JOB_STATUS_CREATED);
+ aio_timer_init(qemu_get_aio_context(), &job->sleep_timer,
+ QEMU_CLOCK_REALTIME, SCALE_NS,
+ job_sleep_timer_cb, job);
QLIST_INSERT_HEAD(&jobs, job, job_list);
@@ -193,6 +203,7 @@ void job_unref(Job *job)
{
if (--job->refcnt == 0) {
assert(job->status == JOB_STATUS_NULL);
+ assert(!timer_pending(&job->sleep_timer));
if (job->driver->free) {
job->driver->free(job);
@@ -232,6 +243,11 @@ void job_enter_cond(Job *job, bool(*fn)(Job *job))
aio_co_wake(job->co);
}
+void job_enter(Job *job)
+{
+ job_enter_cond(job, NULL);
+}
+
/* Yield, and schedule a timer to reenter the coroutine after @ns nanoseconds.
* Reentering the job coroutine with block_job_enter() before the timer has
* expired is allowed and cancels the timer.
@@ -283,6 +299,22 @@ void coroutine_fn job_pause_point(Job *job)
}
}
+void coroutine_fn job_sleep_ns(Job *job, int64_t ns)
+{
+ assert(job->busy);
+
+ /* Check cancellation *before* setting busy = false, too! */
+ if (job_is_cancelled(job)) {
+ return;
+ }
+
+ if (!job_should_pause(job)) {
+ job_do_yield(job, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ns);
+ }
+
+ job_pause_point(job);
+}
+
/**
* All jobs must allow a pause point before entering their job proper. This
* ensures that jobs can be paused prior to being started, then resumed later.