aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2018-04-13 17:31:02 +0200
committerKevin Wolf <kwolf@redhat.com>2018-05-23 14:30:50 +0200
commitda01ff7f38f52791f93fc3ca59afcfbb220f15af (patch)
tree74010498c6229085ce3f2cc2184168aec5fb99f8 /include
parent1908a5590c7d214b1b6886bc19b81076fb65cec9 (diff)
downloadqemu-da01ff7f38f52791f93fc3ca59afcfbb220f15af.zip
qemu-da01ff7f38f52791f93fc3ca59afcfbb220f15af.tar.gz
qemu-da01ff7f38f52791f93fc3ca59afcfbb220f15af.tar.bz2
job: Move coroutine and related code to Job
This commit moves some core functions for dealing with the job coroutine from BlockJob to Job. This includes primarily entering the coroutine (both for the first and reentering) and yielding explicitly and at pause points. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com>
Diffstat (limited to 'include')
-rw-r--r--include/block/blockjob.h40
-rw-r--r--include/block/blockjob_int.h26
-rw-r--r--include/qemu/job.h76
3 files changed, 76 insertions, 66 deletions
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index 2a9e865..b60d919 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -51,43 +51,18 @@ typedef struct BlockJob {
BlockBackend *blk;
/**
- * The coroutine that executes the job. If not NULL, it is
- * reentered when busy is false and the job is cancelled.
- */
- Coroutine *co;
-
- /**
* Set to true if the job should abort immediately without waiting
* for data to be in sync.
*/
bool force;
/**
- * Counter for pause request. If non-zero, the block job is either paused,
- * or if busy == true will pause itself as soon as possible.
- */
- int pause_count;
-
- /**
* Set to true if the job is paused by user. Can be unpaused with the
* block-job-resume QMP command.
*/
bool user_paused;
/**
- * Set to false by the job while the coroutine has yielded and may be
- * re-entered by block_job_enter(). There may still be I/O or event loop
- * activity pending. Accessed under block_job_mutex (in blockjob.c).
- */
- bool busy;
-
- /**
- * Set to true by the job while it is in a quiescent state, where
- * no I/O or event loop activity is pending.
- */
- bool paused;
-
- /**
* Set to true when the job is ready to be completed.
*/
bool ready;
@@ -125,12 +100,6 @@ typedef struct BlockJob {
/** ret code passed to block_job_completed. */
int ret;
- /**
- * Timer that is used by @block_job_sleep_ns. Accessed under
- * block_job_mutex (in blockjob.c).
- */
- QEMUTimer sleep_timer;
-
/** True if this job should automatically finalize itself */
bool auto_finalize;
@@ -208,15 +177,6 @@ void block_job_remove_all_bdrv(BlockJob *job);
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
/**
- * block_job_start:
- * @job: A job that has not yet been started.
- *
- * Begins execution of a block job.
- * Takes ownership of one reference to the job object.
- */
-void block_job_start(BlockJob *job);
-
-/**
* block_job_cancel:
* @job: The job to be canceled.
* @force: Quit a job without waiting for data to be in sync.
diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h
index 0c2f8de..0a614a8 100644
--- a/include/block/blockjob_int.h
+++ b/include/block/blockjob_int.h
@@ -38,9 +38,6 @@ struct BlockJobDriver {
/** Generic JobDriver callbacks and settings */
JobDriver job_driver;
- /** Mandatory: Entrypoint for the Coroutine. */
- CoroutineEntry *start;
-
/**
* Optional callback for job types whose completion must be triggered
* manually.
@@ -85,20 +82,6 @@ struct BlockJobDriver {
*/
void (*clean)(BlockJob *job);
- /**
- * If the callback is not NULL, it will be invoked when the job transitions
- * into the paused state. Paused jobs must not perform any asynchronous
- * I/O or event loop activity. This callback is used to quiesce jobs.
- */
- void coroutine_fn (*pause)(BlockJob *job);
-
- /**
- * If the callback is not NULL, it will be invoked when the job transitions
- * out of the paused state. Any asynchronous I/O or event loop activity
- * should be restarted from this callback.
- */
- void coroutine_fn (*resume)(BlockJob *job);
-
/*
* If the callback is not NULL, it will be invoked before the job is
* resumed in a new AioContext. This is the place to move any resources
@@ -196,15 +179,6 @@ void block_job_early_fail(BlockJob *job);
void block_job_completed(BlockJob *job, int ret);
/**
- * block_job_pause_point:
- * @job: The job that is ready to pause.
- *
- * Pause now if block_job_pause() has been called. Block jobs that perform
- * lots of I/O must call this between requests so that the job can be paused.
- */
-void coroutine_fn block_job_pause_point(BlockJob *job);
-
-/**
* block_job_enter:
* @job: The job to enter.
*
diff --git a/include/qemu/job.h b/include/qemu/job.h
index 933e0ab..9dcff12 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -28,6 +28,7 @@
#include "qapi/qapi-types-block-core.h"
#include "qemu/queue.h"
+#include "qemu/coroutine.h"
typedef struct JobDriver JobDriver;
@@ -51,6 +52,37 @@ typedef struct Job {
AioContext *aio_context;
/**
+ * The coroutine that executes the job. If not NULL, it is reentered when
+ * busy is false and the job is cancelled.
+ */
+ Coroutine *co;
+
+ /**
+ * Timer that is used by @block_job_sleep_ns. Accessed under job_mutex (in
+ * job.c).
+ */
+ QEMUTimer sleep_timer;
+
+ /**
+ * Counter for pause request. If non-zero, the block job is either paused,
+ * or if busy == true will pause itself as soon as possible.
+ */
+ int pause_count;
+
+ /**
+ * Set to false by the job while the coroutine has yielded and may be
+ * re-entered by block_job_enter(). There may still be I/O or event loop
+ * activity pending. Accessed under block_job_mutex (in blockjob.c).
+ */
+ bool busy;
+
+ /**
+ * Set to true by the job while it is in a quiescent state, where
+ * no I/O or event loop activity is pending.
+ */
+ bool paused;
+
+ /**
* Set to true if the job should cancel itself. The flag must
* always be tested just before toggling the busy flag from false
* to true. After a job has been cancelled, it should only yield
@@ -75,6 +107,23 @@ struct JobDriver {
/** Enum describing the operation */
JobType job_type;
+ /** Mandatory: Entrypoint for the Coroutine. */
+ CoroutineEntry *start;
+
+ /**
+ * If the callback is not NULL, it will be invoked when the job transitions
+ * into the paused state. Paused jobs must not perform any asynchronous
+ * I/O or event loop activity. This callback is used to quiesce jobs.
+ */
+ void coroutine_fn (*pause)(Job *job);
+
+ /**
+ * If the callback is not NULL, it will be invoked when the job transitions
+ * out of the paused state. Any asynchronous I/O or event loop activity
+ * should be restarted from this callback.
+ */
+ void coroutine_fn (*resume)(Job *job);
+
/** Called when the job is freed */
void (*free)(Job *job);
};
@@ -103,6 +152,30 @@ void job_ref(Job *job);
*/
void job_unref(Job *job);
+/**
+ * Conditionally enter the job coroutine if the job is ready to run, not
+ * already busy and fn() returns true. fn() is called while under the job_lock
+ * critical section.
+ */
+void job_enter_cond(Job *job, bool(*fn)(Job *job));
+
+/**
+ * @job: A job that has not yet been started.
+ *
+ * Begins execution of a job.
+ * Takes ownership of one reference to the job object.
+ */
+void job_start(Job *job);
+
+/**
+ * @job: The job that is ready to pause.
+ *
+ * Pause now if job_pause() has been called. Jobs that perform lots of I/O
+ * must call this between requests so that the job can be paused.
+ */
+void coroutine_fn job_pause_point(Job *job);
+
+
/** Returns the JobType of a given Job. */
JobType job_type(const Job *job);
@@ -153,5 +226,8 @@ void job_defer_to_main_loop(Job *job, JobDeferToMainLoopFn *fn, void *opaque);
/* TODO To be removed from the public interface */
void job_state_transition(Job *job, JobStatus s1);
+void coroutine_fn job_do_yield(Job *job, uint64_t ns);
+bool job_should_pause(Job *job);
+bool job_started(Job *job);
#endif