Make epicsMutex intialization use epicsThreadOnceId

Includes Michael's patch to replace calls to the epicsMutex API
from inside the libCom/osi/os/RTEMS/osdThread.c code.

Fixes lp:1542539
This commit is contained in:
Andrew Johnson
2016-02-29 16:22:43 -06:00
parent 0f6f833e91
commit 64cd49410e
2 changed files with 68 additions and 47 deletions

View File

@@ -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 =

View File

@@ -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, &note);
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++)