thread pool: handle failure to create worker

epicsJobQueue() returns EAGAIN when the first worker
can't be lazily created.

Failure to create workers beyond the first is
silently ignored.
This commit is contained in:
Michael Davidsaver
2014-07-24 18:50:19 -04:00
parent 69d1063067
commit 83dfc7980d
3 changed files with 33 additions and 12 deletions

View File

@@ -123,7 +123,7 @@ void workerMain(void* arg)
return;
}
void createPoolThread(epicsThreadPool *pool)
int createPoolThread(epicsThreadPool *pool)
{
epicsThreadId tid;
@@ -133,10 +133,11 @@ void createPoolThread(epicsThreadPool *pool)
&workerMain,
pool);
if(!tid)
return;
return 1;
pool->threadsRunning++;
pool->threadsSleeping++;
return 0;
}
epicsJob* epicsJobCreate(epicsThreadPool* pool,
@@ -277,10 +278,27 @@ int epicsJobQueue(epicsJob* job)
/* could create more workers so
* will either create a new worker, or wakeup an existing worker
*/
pool->threadsWaking++;
epicsEventSignal(pool->workerWakeup);
if(pool->threadsWaking > pool->threadsSleeping)
createPoolThread(pool);
if(pool->threadsWaking >= pool->threadsSleeping) {
/* all sleeping workers have already been woken.
* start a new worker for this job
*/
if(createPoolThread(pool) && pool->threadsRunning==0) {
/* oops, we couldn't lazy create our first worker
* so this job would never run!
*/
ret = EAGAIN;
job->queued = 0;
/* if threadsRunning==0 then no jobs can be running */
assert(!job->running);
ellDelete(&pool->jobs, &job->jobnode);
ellAdd(&pool->owned, &job->jobnode);
}
}
if(ret==0) {
pool->threadsWaking++;
epicsEventSignal(pool->workerWakeup);
}
CHECKCOUNT(pool);
}

View File

@@ -92,6 +92,6 @@ struct epicsJob {
unsigned int dead:1; /* flag to catch use of freed objects */
};
void createPoolThread(epicsThreadPool *pool);
int createPoolThread(epicsThreadPool *pool);
#endif // POOLPRIV_H

View File

@@ -77,9 +77,8 @@ epicsThreadPool* epicsThreadPoolCreate(epicsThreadPoolConfig *opts)
createPoolThread(pool);
}
epicsMutexUnlock(pool->guard);
if(pool->threadsRunning==0 && pool->conf.initialThreads!=0) {
epicsMutexUnlock(pool->guard);
errlogPrintf("Error: Unable to create any threads for thread pool\n");
goto cleanup;
@@ -89,6 +88,8 @@ epicsThreadPool* epicsThreadPoolCreate(epicsThreadPoolConfig *opts)
(unsigned long)pool->conf.initialThreads);
}
epicsMutexUnlock(pool->guard);
return pool;
cleanup:
@@ -131,9 +132,11 @@ void _epicsThreadPoolControl(epicsThreadPool* pool, epicsThreadPoolOption opt, u
}
}
while(jobs-- && pool->threadsRunning < pool->conf.maxThreads) {
pool->threadsWaking++;
epicsEventSignal(pool->workerWakeup);
createPoolThread(pool);
if(createPoolThread(pool)==0) {
pool->threadsWaking++;
epicsEventSignal(pool->workerWakeup);
} else
break; /* oops, couldn't create worker */
}
CHECKCOUNT(pool);
}