diff --git a/src/libCom/pool/poolJob.c b/src/libCom/pool/poolJob.c index 46db31d0e..f7e9baa88 100644 --- a/src/libCom/pool/poolJob.c +++ b/src/libCom/pool/poolJob.c @@ -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); } diff --git a/src/libCom/pool/poolPriv.h b/src/libCom/pool/poolPriv.h index 789ea57a6..4ad0d112c 100644 --- a/src/libCom/pool/poolPriv.h +++ b/src/libCom/pool/poolPriv.h @@ -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 diff --git a/src/libCom/pool/threadPool.c b/src/libCom/pool/threadPool.c index 4a7c03ea1..ccdc7f2b1 100644 --- a/src/libCom/pool/threadPool.c +++ b/src/libCom/pool/threadPool.c @@ -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); }