Count number of threads active in each class, and reserve threads only if none active
This commit is contained in:
@@ -51,9 +51,9 @@ struct private_processor_t {
|
|||||||
u_int desired_threads;
|
u_int desired_threads;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of threads waiting for work
|
* Number of threads currently working, for each priority
|
||||||
*/
|
*/
|
||||||
u_int idle_threads;
|
u_int working_threads[JOB_PRIO_MAX];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All threads managed in the pool (including threads that have been
|
* All threads managed in the pool (including threads that have been
|
||||||
@@ -113,6 +113,29 @@ static void restart(private_processor_t *this)
|
|||||||
this->mutex->unlock(this->mutex);
|
this->mutex->unlock(this->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrement working thread count of a priority class
|
||||||
|
*/
|
||||||
|
static void decrement_working_threads(u_int *working_threads)
|
||||||
|
{
|
||||||
|
(*working_threads)--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get number of idle threads, non-locking variant
|
||||||
|
*/
|
||||||
|
static u_int get_idle_threads_nolock(private_processor_t *this)
|
||||||
|
{
|
||||||
|
u_int count, i;
|
||||||
|
|
||||||
|
count = this->total_threads;
|
||||||
|
for (i = 0; i < JOB_PRIO_MAX; i++)
|
||||||
|
{
|
||||||
|
count -= this->working_threads[i];
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process queued jobs, called by the worker threads
|
* Process queued jobs, called by the worker threads
|
||||||
*/
|
*/
|
||||||
@@ -127,37 +150,43 @@ static void process_jobs(private_processor_t *this)
|
|||||||
while (this->desired_threads >= this->total_threads)
|
while (this->desired_threads >= this->total_threads)
|
||||||
{
|
{
|
||||||
job_t *job = NULL;
|
job_t *job = NULL;
|
||||||
int i, prio_sum = 0;
|
int i, reserved = 0, idle;
|
||||||
|
|
||||||
|
idle = get_idle_threads_nolock(this);
|
||||||
|
|
||||||
for (i = 0; i < JOB_PRIO_MAX; i++)
|
for (i = 0; i < JOB_PRIO_MAX; i++)
|
||||||
{
|
{
|
||||||
if (prio_sum && prio_sum >= this->idle_threads)
|
if (reserved && reserved >= idle)
|
||||||
{
|
{
|
||||||
DBG2(DBG_JOB, "delaying %N priority jobs: %d threads idle, "
|
DBG2(DBG_JOB, "delaying %N priority jobs: %d threads idle, "
|
||||||
"but %d reserved for higher priorities",
|
"but %d reserved for higher priorities",
|
||||||
job_priority_names, i, this->idle_threads, prio_sum);
|
job_priority_names, i, idle, reserved);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
prio_sum += this->prio_threads[i];
|
if (this->working_threads[i] < this->prio_threads[i])
|
||||||
|
{
|
||||||
|
reserved += this->prio_threads[i] - this->working_threads[i];
|
||||||
|
}
|
||||||
if (this->jobs[i]->remove_first(this->jobs[i],
|
if (this->jobs[i]->remove_first(this->jobs[i],
|
||||||
(void**)&job) == SUCCESS)
|
(void**)&job) == SUCCESS)
|
||||||
{
|
{
|
||||||
|
this->working_threads[i]++;
|
||||||
|
this->mutex->unlock(this->mutex);
|
||||||
|
thread_cleanup_push((thread_cleanup_t)decrement_working_threads,
|
||||||
|
&this->working_threads[i]);
|
||||||
|
/* terminated threads are restarted to get a constant pool */
|
||||||
|
thread_cleanup_push((thread_cleanup_t)restart, this);
|
||||||
|
job->execute(job);
|
||||||
|
thread_cleanup_pop(FALSE);
|
||||||
|
this->mutex->lock(this->mutex);
|
||||||
|
thread_cleanup_pop(TRUE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!job)
|
if (!job)
|
||||||
{
|
{
|
||||||
this->idle_threads++;
|
|
||||||
this->job_added->wait(this->job_added, this->mutex);
|
this->job_added->wait(this->job_added, this->mutex);
|
||||||
this->idle_threads--;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
this->mutex->unlock(this->mutex);
|
|
||||||
/* terminated threads are restarted, so we have a constant pool */
|
|
||||||
thread_cleanup_push((thread_cleanup_t)restart, this);
|
|
||||||
job->execute(job);
|
|
||||||
thread_cleanup_pop(FALSE);
|
|
||||||
this->mutex->lock(this->mutex);
|
|
||||||
}
|
}
|
||||||
this->total_threads--;
|
this->total_threads--;
|
||||||
this->thread_terminated->signal(this->thread_terminated);
|
this->thread_terminated->signal(this->thread_terminated);
|
||||||
@@ -181,7 +210,7 @@ METHOD(processor_t, get_idle_threads, u_int,
|
|||||||
u_int count;
|
u_int count;
|
||||||
|
|
||||||
this->mutex->lock(this->mutex);
|
this->mutex->lock(this->mutex);
|
||||||
count = this->idle_threads;
|
count = get_idle_threads_nolock(this);
|
||||||
this->mutex->unlock(this->mutex);
|
this->mutex->unlock(this->mutex);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@@ -198,6 +227,17 @@ static job_priority_t sane_prio(job_priority_t prio)
|
|||||||
return prio;
|
return prio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(processor_t, get_working_threads, u_int,
|
||||||
|
private_processor_t *this, job_priority_t prio)
|
||||||
|
{
|
||||||
|
u_int count;
|
||||||
|
|
||||||
|
this->mutex->lock(this->mutex);
|
||||||
|
count = this->working_threads[sane_prio(prio)];
|
||||||
|
this->mutex->unlock(this->mutex);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(processor_t, get_job_load, u_int,
|
METHOD(processor_t, get_job_load, u_int,
|
||||||
private_processor_t *this, job_priority_t prio)
|
private_processor_t *this, job_priority_t prio)
|
||||||
{
|
{
|
||||||
@@ -293,6 +333,7 @@ processor_t *processor_create()
|
|||||||
.public = {
|
.public = {
|
||||||
.get_total_threads = _get_total_threads,
|
.get_total_threads = _get_total_threads,
|
||||||
.get_idle_threads = _get_idle_threads,
|
.get_idle_threads = _get_idle_threads,
|
||||||
|
.get_working_threads = _get_working_threads,
|
||||||
.get_job_load = _get_job_load,
|
.get_job_load = _get_job_load,
|
||||||
.queue_job = _queue_job,
|
.queue_job = _queue_job,
|
||||||
.set_threads = _set_threads,
|
.set_threads = _set_threads,
|
||||||
|
|||||||
@@ -42,12 +42,20 @@ struct processor_t {
|
|||||||
u_int (*get_total_threads) (processor_t *this);
|
u_int (*get_total_threads) (processor_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of threads currently waiting.
|
* Get the number of threads currently waiting for work.
|
||||||
*
|
*
|
||||||
* @return number of idle threads
|
* @return number of idle threads
|
||||||
*/
|
*/
|
||||||
u_int (*get_idle_threads) (processor_t *this);
|
u_int (*get_idle_threads) (processor_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of threads currently working, per priority class.
|
||||||
|
*
|
||||||
|
* @param prioritiy to check
|
||||||
|
* @return number of threads in priority working
|
||||||
|
*/
|
||||||
|
u_int (*get_working_threads)(processor_t *this, job_priority_t prio);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of queued jobs for a specified priority.
|
* Get the number of queued jobs for a specified priority.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user