added capability to record the last owner of the mutex, but perhaps

this should be active only with debug builds
This commit is contained in:
Jeff Hill
2002-12-11 23:01:49 +00:00
parent 3c136f74d8
commit fa1b9181cb
7 changed files with 153 additions and 106 deletions

View File

@@ -30,20 +30,20 @@ STATIC int firstTime = 1;
STATIC ELLLIST mutexList;
STATIC ELLLIST freeList;
typedef struct mutexNode {
struct epicsMutexParm {
ELLNODE node;
epicsMutexId id;
epicsMutexOSD * id;
epicsThreadId lastOwner;
const char *pFileName;
int lineno;
}mutexNode;
};
STATIC epicsMutexId epicsMutexGlobalLock;
STATIC epicsMutexOSD * epicsMutexGlobalLock;
epicsMutexId epicsShareAPI epicsMutexOsiCreate(
const char *pFileName,int lineno)
{
epicsMutexId id;
mutexNode *pmutexNode;
epicsMutexOSD * id;
if(firstTime) {
firstTime=0;
@@ -51,22 +51,27 @@ epicsMutexId epicsShareAPI epicsMutexOsiCreate(
ellInit(&freeList);
epicsMutexGlobalLock = epicsMutexOsdCreate();
}
epicsMutexMustLock(epicsMutexGlobalLock);
id = epicsMutexOsdCreate();
if(id) {
pmutexNode = reinterpret_cast < mutexNode * > ( ellFirst(&freeList) );
if(pmutexNode) {
ellDelete(&freeList,&pmutexNode->node);
} else {
pmutexNode = static_cast < mutexNode * > ( calloc(1,sizeof(mutexNode)) );
}
pmutexNode->id = id;
pmutexNode->pFileName = pFileName;
pmutexNode->lineno = lineno;
ellAdd(&mutexList,&pmutexNode->node);
if(!id) {
return 0;
}
epicsMutexUnlock(epicsMutexGlobalLock);
return(id);
epicsMutexLockStatus lockStat =
epicsMutexOsdLock(epicsMutexGlobalLock);
assert ( lockStat == epicsMutexLockOK );
epicsMutexParm *pmutexNode =
reinterpret_cast < epicsMutexParm * > ( ellFirst(&freeList) );
if(pmutexNode) {
ellDelete(&freeList,&pmutexNode->node);
} else {
pmutexNode = static_cast < epicsMutexParm * > ( calloc(1,sizeof(epicsMutexParm)) );
}
pmutexNode->id = id;
pmutexNode->lastOwner = 0;
pmutexNode->pFileName = pFileName;
pmutexNode->lineno = lineno;
ellAdd(&mutexList,&pmutexNode->node);
epicsMutexOsdUnlock(epicsMutexGlobalLock);
return(pmutexNode);
}
epicsMutexId epicsShareAPI epicsMutexOsiMustCreate(
@@ -77,54 +82,91 @@ epicsMutexId epicsShareAPI epicsMutexOsiMustCreate(
return(id );
}
void epicsShareAPI epicsMutexDestroy(epicsMutexId id)
void epicsShareAPI epicsMutexDestroy(epicsMutexId pmutexNode)
{
mutexNode *pmutexNode;
epicsMutexLockStatus lockStat =
epicsMutexOsdLock(epicsMutexGlobalLock);
assert ( lockStat == epicsMutexLockOK );
ellDelete(&mutexList,&pmutexNode->node);
epicsMutexOsdDestroy(pmutexNode->id);
ellAdd(&freeList,&pmutexNode->node);
epicsMutexOsdUnlock(epicsMutexGlobalLock);
}
epicsMutexMustLock(epicsMutexGlobalLock);
pmutexNode = reinterpret_cast < mutexNode * > ( ellLast(&mutexList) );
while(pmutexNode) {
if(id==pmutexNode->id) {
ellDelete(&mutexList,&pmutexNode->node);
ellAdd(&freeList,&pmutexNode->node);
epicsMutexOsdDestroy(pmutexNode->id);
epicsMutexUnlock(epicsMutexGlobalLock);
return;
}
pmutexNode =
reinterpret_cast < mutexNode * > ( ellPrevious(&pmutexNode->node) );
void epicsShareAPI epicsMutexUnlock(epicsMutexId pmutexNode)
{
epicsMutexOsdUnlock(pmutexNode->id);
}
epicsMutexLockStatus epicsShareAPI epicsMutexLock(
epicsMutexId pmutexNode)
{
epicsMutexLockStatus status =
epicsMutexOsdLock(pmutexNode->id);
if ( status == epicsMutexLockOK ) {
pmutexNode->lastOwner = epicsThreadGetIdSelf();
}
return status;
}
epicsMutexLockStatus epicsShareAPI epicsMutexTryLock(
epicsMutexId pmutexNode)
{
epicsMutexLockStatus status =
epicsMutexOsdTryLock(pmutexNode->id);
if ( status == epicsMutexLockOK ) {
pmutexNode->lastOwner = epicsThreadGetIdSelf();
}
return status;
}
void epicsShareAPI epicsMutexShow(
epicsMutexId pmutexNode, unsigned int level)
{
char threadName [255];
if ( pmutexNode->lastOwner ) {
epicsThreadGetName ( pmutexNode->lastOwner,
threadName, sizeof ( threadName ) );
}
else {
strcpy ( threadName, "<not used>" );
}
printf("epicsMutexId %p last owner \"%s\" source %s line %d\n",
(void *)pmutexNode, threadName,
pmutexNode->pFileName, pmutexNode->lineno);
if ( level > 0 ) {
epicsMutexOsdShow(pmutexNode->id,level-1);
}
epicsMutexUnlock(epicsMutexGlobalLock);
errlogPrintf("epicsMutexDestroy Did not find epicsMutexId\n");
}
void epicsShareAPI epicsMutexShowAll(int onlyLocked,unsigned int level)
{
mutexNode *pmutexNode;
epicsMutexParm *pmutexNode;
if(firstTime) return;
printf("ellCount(&mutexList) %d ellCount(&freeList) %d\n",
ellCount(&mutexList),ellCount(&freeList));
epicsMutexMustLock(epicsMutexGlobalLock);
pmutexNode = reinterpret_cast < mutexNode * > ( ellFirst(&mutexList) );
epicsMutexLockStatus lockStat =
epicsMutexOsdLock(epicsMutexGlobalLock);
assert ( lockStat == epicsMutexLockOK );
pmutexNode = reinterpret_cast < epicsMutexParm * > ( ellFirst(&mutexList) );
while(pmutexNode) {
if(onlyLocked) {
epicsMutexLockStatus status;
status = epicsMutexTryLock(pmutexNode->id);
status = epicsMutexOsdTryLock(pmutexNode->id);
if(status==epicsMutexLockOK) {
epicsMutexUnlock(pmutexNode->id);
epicsMutexOsdUnlock(pmutexNode->id);
pmutexNode =
reinterpret_cast < mutexNode * > ( ellNext(&pmutexNode->node) );
reinterpret_cast < epicsMutexParm * >
( ellNext(&pmutexNode->node) );
continue;
}
}
printf("epicsMutexId %p source %s line %d\n",
(void *)pmutexNode->id,pmutexNode->pFileName,pmutexNode->lineno);
epicsMutexShow(pmutexNode->id,level);
epicsMutexShow(pmutexNode, level);
pmutexNode =
reinterpret_cast < mutexNode * > ( ellNext(&pmutexNode->node) );
reinterpret_cast < epicsMutexParm * > ( ellNext(&pmutexNode->node) );
}
epicsMutexUnlock(epicsMutexGlobalLock);
epicsMutexOsdUnlock(epicsMutexGlobalLock);
}
epicsMutex :: epicsMutex () epicsThrows (( epicsMutex::mutexCreateFailed )) :

View File

@@ -14,7 +14,7 @@
#include "shareLib.h"
typedef struct epicsMutexOSD *epicsMutexId;
typedef struct epicsMutexParm *epicsMutexId;
typedef enum {
epicsMutexLockOK,epicsMutexLockTimeout,epicsMutexLockError
} epicsMutexLockStatus;
@@ -50,16 +50,13 @@ private:
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus*/
/* The following should NOT be called by user code*/
epicsShareFunc epicsMutexId epicsShareAPI epicsMutexOsdCreate(void);
epicsShareFunc void epicsShareAPI epicsMutexOsdDestroy(epicsMutexId id);
epicsShareFunc epicsMutexId epicsShareAPI epicsMutexOsiCreate(
const char *pFileName,int lineno);
epicsShareFunc epicsMutexId epicsShareAPI epicsMutexOsiMustCreate(
const char *pFileName,int lineno);
#define epicsMutexCreate() epicsMutexOsiCreate(__FILE__,__LINE__)
epicsShareFunc epicsMutexId epicsShareAPI epicsMutexOsiCreate(
const char *pFileName,int lineno);
#define epicsMutexMustCreate() epicsMutexOsiMustCreate(__FILE__,__LINE__)
epicsShareFunc epicsMutexId epicsShareAPI epicsMutexOsiMustCreate(
const char *pFileName,int lineno);
epicsShareFunc void epicsShareAPI epicsMutexDestroy(epicsMutexId id);
epicsShareFunc void epicsShareAPI epicsMutexUnlock(epicsMutexId id);
epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexLock(
@@ -77,6 +74,18 @@ epicsShareFunc void epicsShareAPI epicsMutexShowAll(
epicsMutex should implement priority inheritance and deletion safe
*/
/*
* The following is the interface to the OS dependent
* implementation and should NOT be called directly by
* user code
*/
struct epicsMutexOSD * epicsMutexOsdCreate(void);
void epicsMutexOsdDestroy(struct epicsMutexOSD *);
void epicsMutexOsdUnlock(struct epicsMutexOSD *);
epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD *);
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD *);
void epicsMutexOsdShow(struct epicsMutexOSD *,unsigned int level);
#ifdef __cplusplus
}
#endif

View File

@@ -39,7 +39,7 @@ unsigned long semMstat[4];
#define SEMSTAT(i)
#endif
epicsMutexId
epicsMutexOSD *
epicsMutexOsdCreate(void)
{
rtems_status_code sc;
@@ -92,7 +92,7 @@ epicsMutexOsdCreate(void)
return (epicsMutexId)sid;
}
void epicsMutexOsdDestroy(epicsMutexId id)
void epicsMutexOsdDestroy(struct epicsMutexOSD * id)
{
rtems_status_code sc;
rtems_id sid;
@@ -111,7 +111,7 @@ void epicsMutexOsdDestroy(epicsMutexId id)
errlogPrintf ("Can't destroy semaphore: %s\n", rtems_status_text (sc));
}
void epicsMutexUnlock(epicsMutexId id)
void epicsMutexOsdUnlock(struct epicsMutexOSD * id)
{
#ifdef RTEMS_FAST_MUTEX
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
@@ -128,7 +128,7 @@ void epicsMutexUnlock(epicsMutexId id)
}
epicsMutexLockStatus epicsMutexLock(epicsMutexId id)
epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD * id)
{
#ifdef RTEMS_FAST_MUTEX
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
@@ -153,7 +153,7 @@ epicsMutexLockStatus epicsMutexLock(epicsMutexId id)
#endif
}
epicsMutexLockStatus epicsMutexTryLock(epicsMutexId id)
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * id)
{
#ifdef RTEMS_FAST_MUTEX
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
@@ -185,7 +185,7 @@ epicsMutexLockStatus epicsMutexTryLock(epicsMutexId id)
#endif
}
epicsShareFunc void epicsMutexShow(epicsMutexId id,unsigned int level)
epicsShareFunc void epicsMutexOsdShow(struct epicsMutexOSD * id,unsigned int level)
{
#ifdef RTEMS_FAST_MUTEX
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;

View File

@@ -59,8 +59,7 @@ static LONG weHaveInitialized = 0;
/*
* epicsMutexCreate ()
*/
epicsShareFunc epicsMutexId epicsShareAPI
epicsMutexOsdCreate ( void )
epicsMutexOSD * epicsMutexOsdCreate ( void )
{
epicsMutexOSD * pSem;
@@ -92,8 +91,7 @@ epicsShareFunc epicsMutexId epicsShareAPI
/*
* epicsMutexOsdDestroy ()
*/
epicsShareFunc void epicsShareAPI
epicsMutexOsdDestroy ( epicsMutexId pSem )
void epicsMutexOsdDestroy ( epicsMutexOSD * pSem )
{
if ( thisIsNT ) {
DeleteCriticalSection ( &pSem->os.criticalSection );
@@ -105,10 +103,9 @@ epicsShareFunc void epicsShareAPI
}
/*
* epicsMutexUnlock ()
* epicsMutexOsdUnlock ()
*/
epicsShareFunc void epicsShareAPI
epicsMutexUnlock ( epicsMutexId pSem )
void epicsMutexOsdUnlock ( epicsMutexOSD * pSem )
{
if ( thisIsNT ) {
LeaveCriticalSection ( &pSem->os.criticalSection );
@@ -120,10 +117,9 @@ epicsShareFunc void epicsShareAPI
}
/*
* epicsMutexLock ()
* epicsMutexOsdLock ()
*/
epicsShareFunc epicsMutexLockStatus epicsShareAPI
epicsMutexLock ( epicsMutexId pSem )
epicsMutexLockStatus epicsMutexOsdLock ( epicsMutexOSD * pSem )
{
if ( thisIsNT ) {
EnterCriticalSection ( &pSem->os.criticalSection );
@@ -138,9 +134,9 @@ epicsShareFunc epicsMutexLockStatus epicsShareAPI
}
/*
* epicsMutexTryLock ()
* epicsMutexOsdTryLock ()
*/
epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexTryLock ( epicsMutexId pSem )
epicsMutexLockStatus epicsMutexOsdTryLock ( epicsMutexOSD * pSem )
{
if ( thisIsNT ) {
if ( TryEnterCriticalSection ( &pSem->os.criticalSection ) ) {
@@ -165,9 +161,9 @@ epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexTryLock ( epicsMutex
}
/*
* epicsMutexShow ()
* epicsMutexOsdShow ()
*/
epicsShareFunc void epicsShareAPI epicsMutexShow ( epicsMutexId pSem, unsigned level )
void epicsMutexOsdShow ( epicsMutexOSD * pSem, unsigned level )
{
if ( thisIsNT ) {
printf ("epicsMutex: win32 critical section at %p\n",

View File

@@ -54,7 +54,7 @@ typedef struct epicsMutexOSD {
pthread_mutex_t lock;
}epicsMutexOSD;
epicsMutexId epicsMutexOsdCreate(void) {
epicsMutexOSD * epicsMutexOsdCreate(void) {
epicsMutexOSD *pmutex;
int status;
@@ -70,10 +70,10 @@ epicsMutexId epicsMutexOsdCreate(void) {
if(errVerbose) checkStatus(status,"pthread_mutexattr_settype");
status = pthread_mutex_init(&pmutex->lock,&pmutex->mutexAttr);
checkStatusQuit(status,"pthread_mutex_init","epicsMutexOsdCreate");
return((epicsMutexId)pmutex);
return(pmutex);
}
void epicsMutexOsdDestroy(epicsMutexId pmutex)
void epicsMutexOsdDestroy(struct epicsMutexOSD * pmutex)
{
int status;
@@ -84,25 +84,25 @@ void epicsMutexOsdDestroy(epicsMutexId pmutex)
free(pmutex);
}
void epicsMutexUnlock(epicsMutexId pmutex)
void epicsMutexOsdUnlock(struct epicsMutexOSD * pmutex)
{
int status;
status = pthread_mutex_unlock(&pmutex->lock);
checkStatusQuit(status,"pthread_mutex_unlock","epicsMutexUnlock");
checkStatusQuit(status,"pthread_mutex_unlock","epicsMutexOsdUnlock");
}
epicsMutexLockStatus epicsMutexLock(epicsMutexId pmutex)
epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD * pmutex)
{
int status;
if(!pmutex) return(epicsMutexLockError);
status = pthread_mutex_lock(&pmutex->lock);
checkStatusQuit(status,"pthread_mutex_lock","epicsMutexLock");
checkStatusQuit(status,"pthread_mutex_lock","epicsMutexOsdLock");
return(epicsMutexLockOK);
}
epicsMutexLockStatus epicsMutexTryLock(epicsMutexId pmutex)
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * pmutex)
{
epicsMutexLockStatus status;
int pthreadStatus;
@@ -111,12 +111,12 @@ epicsMutexLockStatus epicsMutexTryLock(epicsMutexId pmutex)
pthreadStatus = pthread_mutex_trylock(&pmutex->lock);
if(pthreadStatus!=0) {
if(pthreadStatus==EBUSY) return(epicsMutexLockTimeout);
checkStatusQuit(pthreadStatus,"pthread_mutex_lock","epicsMutexTryLock");
checkStatusQuit(pthreadStatus,"pthread_mutex_lock","epicsMutexOsdTryLock");
}
return(epicsMutexLockOK);
}
void epicsMutexShow(epicsMutexId pmutex,unsigned int level)
void epicsMutexOsdShow(struct epicsMutexOSD * pmutex,unsigned int level)
{
}
@@ -134,7 +134,7 @@ typedef struct epicsMutexOSD {
pthread_t ownerTid;
}epicsMutexOSD;
epicsMutexId epicsMutexOsdCreate(void) {
epicsMutexOSD * epicsMutexOsdCreate(void) {
epicsMutexOSD *pmutex;
int status;
@@ -159,10 +159,10 @@ epicsMutexId epicsMutexOsdCreate(void) {
status = pthread_cond_init(&pmutex->waitToBeOwner,0);
#endif /*_POSIX_THREAD_PROCESS_SHARED*/
checkStatusQuit(status,"pthread_cond_init","epicsMutexOsdCreate");
return((epicsMutexId)pmutex);
return(pmutex);
}
void epicsMutexOsdDestroy(epicsMutexId pmutex)
void epicsMutexOsdDestroy(struct epicsMutexOSD * pmutex)
{
int status;
@@ -178,16 +178,16 @@ void epicsMutexOsdDestroy(epicsMutexId pmutex)
free(pmutex);
}
void epicsMutexUnlock(epicsMutexId pmutex)
void epicsMutexOsdUnlock(struct epicsMutexOSD * pmutex)
{
int status;
status = pthread_mutex_lock(&pmutex->lock);
checkStatusQuit(status,"pthread_mutex_lock","epicsMutexUnlock");
checkStatusQuit(status,"pthread_mutex_lock","epicsMutexOsdUnlock");
if((pmutex->count<=0) || (pmutex->ownerTid != pthread_self())) {
errlogPrintf("epicsMutexUnlock but caller is not owner\n");
errlogPrintf("epicsMutexOsdUnlock but caller is not owner\n");
status = pthread_mutex_unlock(&pmutex->lock);
checkStatusQuit(status,"pthread_mutex_unlock","epicsMutexUnlock");
checkStatusQuit(status,"pthread_mutex_unlock","epicsMutexOsdUnlock");
return;
}
pmutex->count--;
@@ -197,35 +197,35 @@ void epicsMutexUnlock(epicsMutexId pmutex)
pthread_cond_signal(&pmutex->waitToBeOwner);
}
status = pthread_mutex_unlock(&pmutex->lock);
checkStatusQuit(status,"pthread_mutex_unlock","epicsMutexUnlock");
checkStatusQuit(status,"pthread_mutex_unlock","epicsMutexOsdUnlock");
}
epicsMutexLockStatus epicsMutexLock(epicsMutexId pmutex)
epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD * pmutex)
{
pthread_t tid = pthread_self();
int status;
if(!pmutex || !tid) return(epicsMutexLockError);
status = pthread_mutex_lock(&pmutex->lock);
checkStatusQuit(status,"pthread_mutex_lock","epicsMutexLock");
checkStatusQuit(status,"pthread_mutex_lock","epicsMutexOsdLock");
while(pmutex->owned && !pthread_equal(pmutex->ownerTid,tid))
pthread_cond_wait(&pmutex->waitToBeOwner,&pmutex->lock);
pmutex->ownerTid = tid;
pmutex->owned = 1;
pmutex->count++;
status = pthread_mutex_unlock(&pmutex->lock);
checkStatusQuit(status,"pthread_mutex_unlock","epicsMutexLock");
checkStatusQuit(status,"pthread_mutex_unlock","epicsMutexOsdLock");
return(epicsMutexLockOK);
}
epicsMutexLockStatus epicsMutexTryLock(epicsMutexId pmutex)
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * pmutex)
{
pthread_t tid = pthread_self();
epicsMutexLockStatus status;
int pthreadStatus;
pthreadStatus = pthread_mutex_lock(&pmutex->lock);
checkStatusQuit(pthreadStatus,"pthread_mutex_lock","epicsMutexTryLock");
checkStatusQuit(pthreadStatus,"pthread_mutex_lock","epicsMutexOsdTryLock");
if(!pmutex->owned || pthread_equal(pmutex->ownerTid,tid)) {
pmutex->ownerTid = tid;
pmutex->owned = 1;
@@ -236,11 +236,11 @@ epicsMutexLockStatus epicsMutexTryLock(epicsMutexId pmutex)
status = epicsMutexLockTimeout;
}
pthreadStatus = pthread_mutex_unlock(&pmutex->lock);
checkStatusQuit(pthreadStatus,"pthread_mutex_unlock","epicsMutexTryLock");
checkStatusQuit(pthreadStatus,"pthread_mutex_unlock","epicsMutexOsdTryLock");
return(status);
}
void epicsMutexShow(epicsMutexId pmutex,unsigned int level)
void epicsMutexOsdShow(struct epicsMutexOSD *,unsigned int level)
{
printf("ownerTid %p count %d owned %d\n",
(void *)pmutex->ownerTid,pmutex->count,pmutex->owned);

View File

@@ -22,18 +22,18 @@ int sysClkRateGet(void);
#include "epicsMutex.h"
epicsMutexId epicsMutexOsdCreate(void)
epicsMutexOSD * epicsMutexOsdCreate(void)
{
return((epicsMutexId)
semMCreate(SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY));
}
void epicsMutexOsdDestroy(epicsMutexId id)
void epicsMutexOsdDestroy(struct epicsMutexOSD * id)
{
semDelete((SEM_ID)id);
}
epicsMutexLockStatus epicsMutexTryLock(epicsMutexId id)
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * id)
{
int status;
status = semTake((SEM_ID)id,NO_WAIT);
@@ -42,7 +42,7 @@ epicsMutexLockStatus epicsMutexTryLock(epicsMutexId id)
return(epicsMutexLockError);
}
void epicsMutexShow(epicsMutexId id,unsigned int level)
void epicsMutexOsdShow(struct epicsMutexOSD * id,unsigned int level)
{
semShow((SEM_ID)id,level);
}

View File

@@ -19,7 +19,7 @@
but then a warning message appears everywhere osdMutex.h is included
*/
#define epicsMutexUnlock(ID) semGive((SEM_ID)(ID))
#define epicsMutexOsdUnlock(ID) semGive((SEM_ID)(ID))
#define epicsMutexLock(ID) \
#define epicsMutexOsdLock(ID) \
(semTake((SEM_ID)(ID),WAIT_FOREVER)==OK ? epicsMutexLockOK : epicsMutexLockError)