Give processor_t more control over the lifecycle of a job
Jobs are now destroyed by the processor, but they are allowed to reschedule themselves. That is, parts of the reschedule functionality already provided by callback_job_t is moved to the processor. Not yet fully supported is JOB_REQUEUE_DIRECT and canceling jobs. Note: job_t.destroy() is now called not only for queued jobs but also after execution or cancellation of jobs. job_t.status can be used to decide what to do in said method.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Tobias Brunner
|
||||
* Copyright (C) 2009-2012 Tobias Brunner
|
||||
* Copyright (C) 2007-2011 Martin Willi
|
||||
* Copyright (C) 2011 revosec AG
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
@@ -56,7 +56,7 @@ struct private_callback_job_t {
|
||||
thread_t *thread;
|
||||
|
||||
/**
|
||||
* mutex to access jobs interna
|
||||
* mutex to access private job data
|
||||
*/
|
||||
mutex_t *mutex;
|
||||
|
||||
@@ -71,9 +71,9 @@ struct private_callback_job_t {
|
||||
private_callback_job_t *parent;
|
||||
|
||||
/**
|
||||
* TRUE if the job got cancelled
|
||||
* TRUE if the job got canceled
|
||||
*/
|
||||
bool cancelled;
|
||||
bool canceled;
|
||||
|
||||
/**
|
||||
* condvar to synchronize the cancellation/destruction of the job
|
||||
@@ -103,10 +103,10 @@ static void unregister(private_callback_job_t *this)
|
||||
if (this->parent)
|
||||
{
|
||||
this->parent->mutex->lock(this->parent->mutex);
|
||||
if (this->parent->cancelled && !this->cancelled)
|
||||
if (this->parent->canceled && !this->canceled)
|
||||
{
|
||||
/* if the parent has been cancelled but we have not yet, we do not
|
||||
* unregister until we got cancelled by the parent. */
|
||||
/* if the parent has been canceled but we have not yet, we do not
|
||||
* unregister until we got canceled by the parent. */
|
||||
this->parent->mutex->unlock(this->parent->mutex);
|
||||
this->destroyable->wait(this->destroyable, this->mutex);
|
||||
this->parent->mutex->lock(this->parent->mutex);
|
||||
@@ -144,7 +144,7 @@ METHOD(callback_job_t, cancel, void,
|
||||
semaphore_t *terminated = NULL;
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
this->cancelled = TRUE;
|
||||
this->canceled = TRUE;
|
||||
/* terminate children */
|
||||
while (this->children->get_first(this->children, (void**)&child) == SUCCESS)
|
||||
{
|
||||
@@ -177,12 +177,10 @@ METHOD(callback_job_t, cancel, void,
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(job_t, execute, void,
|
||||
METHOD(job_t, execute, job_requeue_t,
|
||||
private_callback_job_t *this)
|
||||
{
|
||||
bool cleanup = FALSE, requeue = FALSE;
|
||||
|
||||
thread_cleanup_push((thread_cleanup_t)destroy, this);
|
||||
bool requeue = FALSE;
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
this->thread = thread_current();
|
||||
@@ -191,10 +189,9 @@ METHOD(job_t, execute, void,
|
||||
while (TRUE)
|
||||
{
|
||||
this->mutex->lock(this->mutex);
|
||||
if (this->cancelled)
|
||||
if (this->canceled)
|
||||
{
|
||||
this->mutex->unlock(this->mutex);
|
||||
cleanup = TRUE;
|
||||
break;
|
||||
}
|
||||
this->mutex->unlock(this->mutex);
|
||||
@@ -210,7 +207,6 @@ METHOD(job_t, execute, void,
|
||||
case JOB_REQUEUE_NONE:
|
||||
default:
|
||||
{
|
||||
cleanup = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -219,14 +215,10 @@ METHOD(job_t, execute, void,
|
||||
this->mutex->lock(this->mutex);
|
||||
this->thread = NULL;
|
||||
this->mutex->unlock(this->mutex);
|
||||
/* manually create a cancellation point to avoid that a cancelled thread
|
||||
* goes back into the thread pool */
|
||||
/* manually create a cancellation point to avoid that a canceled thread
|
||||
* goes back into the thread pool at all */
|
||||
thread_cancellation_point();
|
||||
if (requeue)
|
||||
{
|
||||
lib->processor->queue_job(lib->processor, &this->public.job);
|
||||
}
|
||||
thread_cleanup_pop(cleanup);
|
||||
return requeue ? JOB_REQUEUE_FAIR : JOB_REQUEUE_NONE;
|
||||
}
|
||||
|
||||
METHOD(job_t, get_priority, job_priority_t,
|
||||
|
||||
@@ -27,33 +27,6 @@ typedef struct callback_job_t callback_job_t;
|
||||
#include <library.h>
|
||||
#include <processing/jobs/job.h>
|
||||
|
||||
|
||||
typedef enum job_requeue_t job_requeue_t;
|
||||
|
||||
/**
|
||||
* Job requeueing policy.
|
||||
*
|
||||
* The job requeueing policy defines how a job is handled when the callback
|
||||
* function returns.
|
||||
*/
|
||||
enum job_requeue_t {
|
||||
|
||||
/**
|
||||
* Do not requeue job, destroy it
|
||||
*/
|
||||
JOB_REQUEUE_NONE,
|
||||
|
||||
/**
|
||||
* Reque the job fairly, meaning it has to requeue as any other job
|
||||
*/
|
||||
JOB_REQUEUE_FAIR,
|
||||
|
||||
/**
|
||||
* Reexecute the job directly, without the need of requeueing it
|
||||
*/
|
||||
JOB_REQUEUE_DIRECT,
|
||||
};
|
||||
|
||||
/**
|
||||
* The callback function to use for the callback job.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Tobias Brunner
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
@@ -24,6 +25,8 @@
|
||||
|
||||
typedef struct job_t job_t;
|
||||
typedef enum job_priority_t job_priority_t;
|
||||
typedef enum job_requeue_t job_requeue_t;
|
||||
typedef enum job_status_t job_status_t;
|
||||
|
||||
#include <library.h>
|
||||
|
||||
@@ -47,19 +50,57 @@ enum job_priority_t {
|
||||
*/
|
||||
extern enum_name_t *job_priority_names;
|
||||
|
||||
/**
|
||||
* Job requeueing policy.
|
||||
*
|
||||
* The job requeueing policy defines how a job is handled after it has been
|
||||
* executed.
|
||||
*/
|
||||
enum job_requeue_t {
|
||||
/** Do not requeue job, destroy it */
|
||||
JOB_REQUEUE_NONE = 0,
|
||||
/** Requeue the job fairly, i.e. it is inserted at the end of the queue */
|
||||
JOB_REQUEUE_FAIR,
|
||||
/** Reexecute the job directly, without the need of requeueing it */
|
||||
JOB_REQUEUE_DIRECT,
|
||||
/** For jobs that rescheduled themselves via scheduler_t */
|
||||
JOB_REQUEUE_SCHEDULED,
|
||||
};
|
||||
|
||||
/**
|
||||
* Job status
|
||||
*/
|
||||
enum job_status_t {
|
||||
/** The job is queued and has not yet been executed */
|
||||
JOB_STATUS_QUEUED = 0,
|
||||
/** During execution */
|
||||
JOB_STATUS_EXECUTING,
|
||||
/** If the job got canceled */
|
||||
JOB_STATUS_CANCELED,
|
||||
/** The job was executed successfully */
|
||||
JOB_STATUS_DONE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Job interface as it is stored in the job queue.
|
||||
*/
|
||||
struct job_t {
|
||||
|
||||
/**
|
||||
* Status of this job, is modified exclusively by the processor/scheduler
|
||||
*/
|
||||
job_status_t status;
|
||||
|
||||
/**
|
||||
* Execute a job.
|
||||
*
|
||||
* The processing facility executes a job using this method. Jobs are
|
||||
* one-shot, they destroy themself after execution, so don't use a job
|
||||
* once it has been executed.
|
||||
* one-shot, they are destroyed after execution (depending on the return
|
||||
* value here), so don't use a job once it has been queued.
|
||||
*
|
||||
* @return policy how to requeue the job
|
||||
*/
|
||||
void (*execute) (job_t *this);
|
||||
job_requeue_t (*execute) (job_t *this);
|
||||
|
||||
/**
|
||||
* Get the priority of a job.
|
||||
@@ -71,8 +112,10 @@ struct job_t {
|
||||
/**
|
||||
* Destroy a job.
|
||||
*
|
||||
* Is only called whenever a job was not executed (e.g. due daemon shutdown).
|
||||
* After execution, jobs destroy themself.
|
||||
* Is called after a job is executed or got canceled. It is also called
|
||||
* for queued jobs that were never executed.
|
||||
*
|
||||
* Use the status of a job to decide what to do during destruction.
|
||||
*/
|
||||
void (*destroy) (job_t *this);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user