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