From b35064d26ccc2d94e95331225f8638a5f02777d0 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sun, 23 Jun 2019 10:36:52 -0700 Subject: [PATCH] Revert "dbEvent simplify db_close_events() with join" This reverts commit 37a76b433a9e7d5a8d26a13fd21ad62f20a0c1c1. # Conflicts: # modules/database/src/ioc/db/dbEvent.c --- modules/database/src/ioc/db/dbEvent.c | 74 ++++++++++++++++++--------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/modules/database/src/ioc/db/dbEvent.c b/modules/database/src/ioc/db/dbEvent.c index 7342a0852..65e3488ad 100644 --- a/modules/database/src/ioc/db/dbEvent.c +++ b/modules/database/src/ioc/db/dbEvent.c @@ -84,6 +84,7 @@ struct event_user { epicsMutexId lock; epicsEventId ppendsem; /* Wait while empty */ epicsEventId pflush_sem; /* wait for flush */ + epicsEventId pexitsem; /* wait for event task to join */ EXTRALABORFUNC *extralabor_sub;/* off load to event task */ void *extralabor_arg;/* parameter to above */ @@ -122,6 +123,8 @@ static char *EVENT_PEND_NAME = "eventTask"; static struct evSubscrip canceledEvent; +static epicsMutexId stopSync; + static unsigned short ringSpace ( const struct event_que *pevq ) { if ( pevq->evque[pevq->putix] == EVENTQEMPTY ) { @@ -260,6 +263,10 @@ int dbel ( const char *pname, unsigned level ) */ void db_init_event_freelists (void) { + if (!stopSync) { + stopSync = epicsMutexMustCreate(); + } + if (!dbevEventUserFreeList) { freeListInitPvt(&dbevEventUserFreeList, sizeof(struct event_user),8); @@ -299,6 +306,9 @@ dbEventCtx db_init_events (void) return NULL; } + /* Flag will be cleared when event task starts */ + evUser->pendexit = TRUE; + evUser->firstque.evUser = evUser; evUser->firstque.writelock = epicsMutexCreate(); if (!evUser->firstque.writelock) @@ -313,6 +323,9 @@ dbEventCtx db_init_events (void) evUser->lock = epicsMutexCreate(); if (!evUser->lock) goto fail; + evUser->pexitsem = epicsEventCreate(epicsEventEmpty); + if (!evUser->pexitsem) + goto fail; evUser->flowCtrlMode = FALSE; evUser->extraLaborBusy = FALSE; @@ -327,6 +340,8 @@ fail: epicsEventDestroy (evUser->ppendsem); if(evUser->pflush_sem) epicsEventDestroy (evUser->pflush_sem); + if(evUser->pexitsem) + epicsEventDestroy (evUser->pexitsem); freeListFree(dbevEventUserFreeList,evUser); return NULL; } @@ -347,6 +362,7 @@ DBCORE_API void db_cleanup_events(void) dbevFieldLogFreeList = NULL; } + /* intentionally leak stopSync to avoid possible shutdown races */ /* * DB_CLOSE_EVENTS() * @@ -368,15 +384,30 @@ void db_close_events (dbEventCtx ctx) * hazardous to the system's health. */ epicsMutexMustLock ( evUser->lock ); - evUser->pendexit = TRUE; + if(!evUser->pendexit) { /* event task running */ + evUser->pendexit = TRUE; + epicsMutexUnlock ( evUser->lock ); + + /* notify the waiting task */ + epicsEventSignal(evUser->ppendsem); + /* wait for task to exit */ + epicsEventMustWait(evUser->pexitsem); + + epicsMutexMustLock ( evUser->lock ); + } + epicsMutexUnlock ( evUser->lock ); - /* notify the waiting task */ - epicsEventSignal(evUser->ppendsem); + epicsMutexMustLock (stopSync); - if(evUser->taskid) - epicsThreadMustJoin(evUser->taskid); - /* evUser has been deleted by the worker */ + epicsEventDestroy(evUser->pexitsem); + epicsEventDestroy(evUser->ppendsem); + epicsEventDestroy(evUser->pflush_sem); + epicsMutexDestroy(evUser->lock); + + epicsMutexUnlock (stopSync); + + freeListFree(dbevEventUserFreeList, evUser); } /* @@ -1063,18 +1094,17 @@ static void event_task (void *pParm) } } - epicsEventDestroy(evUser->ppendsem); - epicsEventDestroy(evUser->pflush_sem); - epicsMutexDestroy(evUser->lock); - - if (dbevEventUserFreeList) - freeListFree(dbevEventUserFreeList, evUser); - else - fprintf(stderr, "%s exiting but dbevEventUserFreeList already NULL\n", - __FUNCTION__); - taskwdRemove(epicsThreadGetIdSelf()); + /* use stopSync to ensure pexitsem is not destroy'd + * until epicsEventSignal() has returned. + */ + epicsMutexMustLock (stopSync); + + epicsEventSignal(evUser->pexitsem); + + epicsMutexUnlock(stopSync); + return; } @@ -1086,11 +1116,6 @@ int db_start_events ( void *init_func_arg, unsigned osiPriority ) { struct event_user * const evUser = (struct event_user *) ctx; - epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT; - - opts.stackSize = epicsThreadGetStackSize(epicsThreadStackMedium); - opts.priority = osiPriority; - opts.joinable = 1; epicsMutexMustLock ( evUser->lock ); @@ -1108,12 +1133,15 @@ int db_start_events ( if (!taskname) { taskname = EVENT_PEND_NAME; } - evUser->taskid = epicsThreadCreateOpt ( - taskname, event_task, (void *)evUser, &opts); + evUser->taskid = epicsThreadCreate ( + taskname, osiPriority, + epicsThreadGetStackSize(epicsThreadStackMedium), + event_task, (void *)evUser); if (!evUser->taskid) { epicsMutexUnlock ( evUser->lock ); return DB_EVENT_ERROR; } + evUser->pendexit = FALSE; epicsMutexUnlock ( evUser->lock ); return DB_EVENT_OK; }