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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user