diff --git a/src/libCom/osi/epicsMutex.cpp b/src/libCom/osi/epicsMutex.cpp index 15d12baa3..8580af204 100644 --- a/src/libCom/osi/epicsMutex.cpp +++ b/src/libCom/osi/epicsMutex.cpp @@ -34,7 +34,7 @@ #include "epicsMutex.h" #include "epicsThread.h" -static int firstTime = 1; +static epicsThreadOnceId epicsMutexOsiOnce = EPICS_THREAD_ONCE_INIT; static ELLLIST mutexList; static ELLLIST freeList; @@ -76,19 +76,20 @@ const char * epicsMutex::invalidMutex::what () const throw () return "epicsMutex::invalidMutex()"; } +static void epicsMutexOsiInit(void *) { + ellInit(&mutexList); + ellInit(&freeList); + VALGRIND_CREATE_MEMPOOL(&freeList, 0, 0); + epicsMutexGlobalLock = epicsMutexOsdCreate(); +} epicsMutexId epicsShareAPI epicsMutexOsiCreate( const char *pFileName,int lineno) { epicsMutexOSD * id; - if(firstTime) { - firstTime=0; - ellInit(&mutexList); - ellInit(&freeList); - VALGRIND_CREATE_MEMPOOL(&freeList, 0, 0); - epicsMutexGlobalLock = epicsMutexOsdCreate(); - } + epicsThreadOnce(&epicsMutexOsiOnce, epicsMutexOsiInit, NULL); + id = epicsMutexOsdCreate(); if(!id) { return 0; @@ -218,7 +219,9 @@ void epicsShareAPI epicsMutexShowAll(int onlyLocked,unsigned int level) { epicsMutexParm *pmutexNode; - if(firstTime) return; + if (epicsMutexOsiOnce == EPICS_THREAD_ONCE_INIT) + return; + printf("ellCount(&mutexList) %d ellCount(&freeList) %d\n", ellCount(&mutexList),ellCount(&freeList)); epicsMutexLockStatus lockStat = diff --git a/src/libCom/osi/os/RTEMS/osdThread.c b/src/libCom/osi/os/RTEMS/osdThread.c index 1fa032820..ed6e73368 100644 --- a/src/libCom/osi/os/RTEMS/osdThread.c +++ b/src/libCom/osi/os/RTEMS/osdThread.c @@ -1,15 +1,12 @@ /*************************************************************************\ * Copyright (c) 2002 The University of Saskatchewan -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* * RTEMS osdThread.c * $Revision-Id$ * Author: W. Eric Norum - * eric@cls.usask.ca - * (306) 966-6055 */ /* @@ -56,15 +53,23 @@ struct taskVar { unsigned int threadVariableCapacity; void **threadVariables; }; -static epicsMutexId taskVarMutex; +static struct epicsMutexOSD *taskVarMutex; static struct taskVar *taskVarHead; #define RTEMS_NOTEPAD_TASKVAR 11 /* * Support for `once-only' execution */ -static int initialized = 0; -static epicsMutexId onceMutex; +static volatile int initialized = 0; /* strictly speaking 'volatile' is not enough here, but it shouldn't hurt */ +static struct epicsMutexOSD *onceMutex; + +static +void epicsMutexOsdMustLock(struct epicsMutexOSD * L) +{ + while(epicsMutexOsdLock(L)!=epicsMutexLockOK) { + cantProceed("epicsThreadOnce() mutex error"); + } +} /* * Just map osi 0 to 99 into RTEMS 199 to 100 @@ -99,7 +104,7 @@ int epicsThreadGetOssPriorityValue(unsigned int osiPriority) /* * epicsThreadLowestPriorityLevelAbove () */ -epicsShareFunc epicsThreadBooleanStatus epicsShareAPI epicsThreadLowestPriorityLevelAbove +epicsShareFunc epicsThreadBooleanStatus epicsThreadLowestPriorityLevelAbove (unsigned int priority, unsigned *pPriorityJustAbove) { unsigned newPriority = priority + 1; @@ -115,7 +120,7 @@ epicsShareFunc epicsThreadBooleanStatus epicsShareAPI epicsThreadLowestPriorityL /* * epicsThreadHighestPriorityLevelBelow () */ -epicsShareFunc epicsThreadBooleanStatus epicsShareAPI epicsThreadHighestPriorityLevelBelow +epicsShareFunc epicsThreadBooleanStatus epicsThreadHighestPriorityLevelBelow (unsigned int priority, unsigned *pPriorityJustBelow) { unsigned newPriority = priority - 1; @@ -150,13 +155,13 @@ epicsThreadGetStackSize (epicsThreadStackSizeClass size) static void taskVarLock (void) { - epicsMutexLock (taskVarMutex); + epicsMutexOsdMustLock (taskVarMutex); } static void taskVarUnlock (void) { - epicsMutexUnlock (taskVarMutex); + epicsMutexOsdUnlock (taskVarMutex); } /* @@ -193,7 +198,8 @@ void epicsThreadExitMain (void) } static void -setThreadInfo (rtems_id tid, const char *name, EPICSTHREADFUNC funptr,void *parm) +setThreadInfo(rtems_id tid, const char *name, EPICSTHREADFUNC funptr, + void *parm) { struct taskVar *v; uint32_t note; @@ -218,7 +224,8 @@ setThreadInfo (rtems_id tid, const char *name, EPICSTHREADFUNC funptr,void *parm if (funptr) { sc = rtems_task_start (tid, threadWrapper, (rtems_task_argument)v); if (sc != RTEMS_SUCCESSFUL) - errlogPrintf ("setThreadInfo: Can't start %s: %s\n",name, rtems_status_text (sc)); + errlogPrintf ("setThreadInfo: Can't start %s: %s\n", + name, rtems_status_text(sc)); } } @@ -236,8 +243,10 @@ epicsThreadInit (void) rtems_task_priority old; rtems_task_set_priority (RTEMS_SELF, epicsThreadGetOssPriorityValue(99), &old); - onceMutex = epicsMutexMustCreate(); - taskVarMutex = epicsMutexMustCreate (); + onceMutex = epicsMutexOsdCreate(); + taskVarMutex = epicsMutexOsdCreate(); + if (!onceMutex || !taskVarMutex) + cantProceed("epicsThreadInit() can't create global mutexes\n"); rtems_task_ident (RTEMS_SELF, 0, &tid); setThreadInfo (tid, "_main_", NULL, NULL); osdThreadHooksRunMain((epicsThreadId)tid); @@ -265,7 +274,8 @@ epicsThreadCreate (const char *name, if (!initialized) epicsThreadInit(); if (stackSize < RTEMS_MINIMUM_STACK_SIZE) { - errlogPrintf ("Warning: epicsThreadCreate %s illegal stackSize %d\n",name,stackSize); + errlogPrintf ("Warning: epicsThreadCreate %s illegal stackSize %d\n", + name, stackSize); stackSize = RTEMS_MINIMUM_STACK_SIZE; } strncpy (c, name, sizeof c); @@ -276,7 +286,8 @@ epicsThreadCreate (const char *name, RTEMS_FLOATING_POINT|RTEMS_LOCAL, &tid); if (sc != RTEMS_SUCCESSFUL) { - errlogPrintf ("epicsThreadCreate create failure for %s: %s\n",name, rtems_status_text (sc)); + errlogPrintf ("epicsThreadCreate create failure for %s: %s\n", + name, rtems_status_text(sc)); return 0; } setThreadInfo (tid, name, funptr,parm); @@ -288,10 +299,10 @@ threadMustCreate (const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr,void *parm) { - epicsThreadId tid; + epicsThreadId tid = epicsThreadCreate(name, priority, stackSize, funptr, parm); - if ((tid = epicsThreadCreate (name, priority, stackSize, funptr, parm)) == NULL) - cantProceed (0); + if (tid == NULL) + cantProceed(0); return tid; } @@ -301,8 +312,9 @@ epicsThreadSuspendSelf (void) rtems_status_code sc; sc = rtems_task_suspend (RTEMS_SELF); - if(sc != RTEMS_SUCCESSFUL) - errlogPrintf("epicsThreadSuspendSelf failed: %s\n", rtems_status_text (sc)); + if (sc != RTEMS_SUCCESSFUL) + errlogPrintf("epicsThreadSuspendSelf failed: %s\n", + rtems_status_text(sc)); } void epicsThreadResume(epicsThreadId id) @@ -311,8 +323,9 @@ void epicsThreadResume(epicsThreadId id) rtems_status_code sc; sc = rtems_task_resume (tid); - if(sc != RTEMS_SUCCESSFUL) - errlogPrintf("epicsThreadResume failed: %s\n", rtems_status_text (sc)); + if (sc != RTEMS_SUCCESSFUL) + errlogPrintf("epicsThreadResume failed: %s\n", + rtems_status_text (sc)); } unsigned int epicsThreadGetPriority(epicsThreadId id) @@ -323,8 +336,9 @@ unsigned int epicsThreadGetPriority(epicsThreadId id) sc = rtems_task_set_priority (tid, RTEMS_CURRENT_PRIORITY, &pri); if (sc != RTEMS_SUCCESSFUL) - errlogPrintf("epicsThreadGetPriority failed: %s\n", rtems_status_text (sc)); - return epicsThreadGetOsiPriorityValue (pri); + errlogPrintf("epicsThreadGetPriority failed: %s\n", + rtems_status_text(sc)); + return epicsThreadGetOsiPriorityValue(pri); } unsigned int epicsThreadGetPrioritySelf(void) @@ -341,7 +355,8 @@ epicsThreadSetPriority (epicsThreadId id,unsigned int osip) sc = rtems_task_set_priority (tid, pri, &pri); if (sc != RTEMS_SUCCESSFUL) - errlogPrintf("epicsThreadSetPriority failed: %s\n", rtems_status_text (sc)); + errlogPrintf("epicsThreadSetPriority failed: %s\n", + rtems_status_text(sc)); } int @@ -385,7 +400,7 @@ epicsThreadSleep (double seconds) } sc = rtems_task_wake_after (delay); if(sc != RTEMS_SUCCESSFUL) - errlogPrintf("epicsThreadSleep: %s\n", rtems_status_text (sc)); + errlogPrintf("epicsThreadSleep: %s\n", rtems_status_text(sc)); } epicsThreadId @@ -425,7 +440,9 @@ void epicsThreadGetName (epicsThreadId id, char *name, size_t size) } taskVarUnlock (); if (!haveName) { -#if (__RTEMS_MAJOR__>4 || (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__>8) || (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__==8 && __RTEMS_REVISION__>=99)) +#if (__RTEMS_MAJOR__>4 || \ + (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__>8) || \ + (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__==8 && __RTEMS_REVISION__>=99)) if (_Objects_Get_name_as_string((rtems_id)id, size, name) != NULL) haveName = 1; #else @@ -486,26 +503,26 @@ void epicsThreadOnce(epicsThreadOnceId *id, void(*func)(void *), void *arg) #define EPICS_THREAD_ONCE_DONE (epicsThreadId) 1 if (!initialized) epicsThreadInit(); - epicsMutexMustLock(onceMutex); + epicsMutexOsdMustLock(onceMutex); if (*id != EPICS_THREAD_ONCE_DONE) { if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */ *id = epicsThreadGetIdSelf(); /* mark active */ - epicsMutexUnlock(onceMutex); + epicsMutexOsdUnlock(onceMutex); func(arg); - epicsMutexMustLock(onceMutex); + epicsMutexOsdMustLock(onceMutex); *id = EPICS_THREAD_ONCE_DONE; /* mark done */ } else if (*id == epicsThreadGetIdSelf()) { - epicsMutexUnlock(onceMutex); + epicsMutexOsdUnlock(onceMutex); cantProceed("Recursive epicsThreadOnce() initialization\n"); } else while (*id != EPICS_THREAD_ONCE_DONE) { /* Another thread is in the above func(arg) call. */ - epicsMutexUnlock(onceMutex); + epicsMutexOsdUnlock(onceMutex); epicsThreadSleep(epicsThreadSleepQuantum()); - epicsMutexMustLock(onceMutex); + epicsMutexOsdMustLock(onceMutex); } } - epicsMutexUnlock(onceMutex); + epicsMutexOsdUnlock(onceMutex); } /* @@ -539,7 +556,8 @@ void epicsThreadPrivateSet (epicsThreadPrivateId id, void *pvt) rtems_task_get_note (RTEMS_SELF, RTEMS_NOTEPAD_TASKVAR, ¬e); v = (struct taskVar *)note; if (varIndex >= v->threadVariableCapacity) { - v->threadVariables = realloc (v->threadVariables, (varIndex + 1) * sizeof (void *)); + v->threadVariables = realloc (v->threadVariables, + (varIndex + 1) * sizeof(void *)); if (v->threadVariables == NULL) cantProceed("epicsThreadPrivateSet realloc failed\n"); for (i = v->threadVariableCapacity ; i < varIndex ; i++)