rationalize osdMutex
Avoids split allocation. Eliminates special case free-list. win32: eliminate pre-XP rtems-score: eliminate non-fast
This commit is contained in:
@ -35,8 +35,6 @@
|
||||
#include "cantProceed.h"
|
||||
#include "epicsExit.h"
|
||||
|
||||
void epicsMutexCleanup(void);
|
||||
|
||||
typedef struct exitNode {
|
||||
ELLNODE node;
|
||||
epicsExitFunc func;
|
||||
@ -115,8 +113,6 @@ LIBCOM_API void epicsExitCallAtExits(void)
|
||||
epicsExitCallAtExitsPvt ( pep );
|
||||
destroyExitPvt ( pep );
|
||||
}
|
||||
/* Handle specially to avoid circular reference */
|
||||
epicsMutexCleanup();
|
||||
}
|
||||
|
||||
LIBCOM_API void epicsExitCallAtThreadExits(void)
|
||||
|
@ -26,30 +26,23 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "epicsStdio.h"
|
||||
#include "epicsThread.h"
|
||||
#include "valgrind/valgrind.h"
|
||||
#include "ellLib.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsMutexImpl.h"
|
||||
#include "epicsThread.h"
|
||||
#include "cantProceed.h"
|
||||
|
||||
static epicsThreadOnceId epicsMutexOsiOnce = EPICS_THREAD_ONCE_INIT;
|
||||
static ELLLIST mutexList;
|
||||
static ELLLIST freeList;
|
||||
|
||||
struct epicsMutexParm {
|
||||
ELLNODE node;
|
||||
epicsMutexOSD * id;
|
||||
# ifdef LOG_LAST_OWNER
|
||||
epicsThreadId lastOwner;
|
||||
# endif
|
||||
const char *pFileName;
|
||||
int lineno;
|
||||
};
|
||||
|
||||
static epicsMutexOSD * epicsMutexGlobalLock;
|
||||
static ELLLIST mutexList = ELLLIST_INIT;
|
||||
|
||||
/* Specially initialized to bootstrap initialization.
|
||||
* When supported (posix and !rtems) use statically initiallized mutex.
|
||||
* Otherwise, initialize via epicsMutexOsdSetup().
|
||||
*/
|
||||
struct epicsMutexParm epicsMutexGlobalLock = {ELLNODE_INIT, __FILE__, __LINE__};
|
||||
|
||||
// vxWorks 5.4 gcc fails during compile when I use std::exception
|
||||
using namespace std;
|
||||
@ -76,176 +69,82 @@ 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 epicsStdCall epicsMutexOsiCreate(
|
||||
const char *pFileName,int lineno)
|
||||
{
|
||||
epicsMutexOSD * id;
|
||||
epicsMutexOsdSetup();
|
||||
|
||||
epicsThreadOnce(&epicsMutexOsiOnce, epicsMutexOsiInit, NULL);
|
||||
epicsMutexId ret = (epicsMutexId)calloc(1, sizeof(*ret));
|
||||
if(ret) {
|
||||
ret->pFileName = pFileName;
|
||||
ret->lineno = lineno;
|
||||
|
||||
if(!epicsMutexOsdPrepare(ret)) {
|
||||
epicsMutexMustLock(&epicsMutexGlobalLock);
|
||||
ellAdd(&mutexList, &ret->node);
|
||||
(void)epicsMutexUnlock(&epicsMutexGlobalLock);
|
||||
|
||||
} else {
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
id = epicsMutexOsdCreate();
|
||||
if(!id) {
|
||||
return 0;
|
||||
}
|
||||
epicsMutexLockStatus lockStat =
|
||||
epicsMutexOsdLock(epicsMutexGlobalLock);
|
||||
assert ( lockStat == epicsMutexLockOK );
|
||||
epicsMutexParm *pmutexNode =
|
||||
reinterpret_cast < epicsMutexParm * > ( ellFirst(&freeList) );
|
||||
if(pmutexNode) {
|
||||
ellDelete(&freeList,&pmutexNode->node);
|
||||
VALGRIND_MEMPOOL_FREE(&freeList, pmutexNode);
|
||||
} else {
|
||||
pmutexNode = static_cast < epicsMutexParm * > ( calloc(1,sizeof(epicsMutexParm)) );
|
||||
}
|
||||
VALGRIND_MEMPOOL_ALLOC(&freeList, pmutexNode, sizeof(epicsMutexParm));
|
||||
pmutexNode->id = id;
|
||||
# ifdef LOG_LAST_OWNER
|
||||
pmutexNode->lastOwner = 0;
|
||||
# endif
|
||||
pmutexNode->pFileName = pFileName;
|
||||
pmutexNode->lineno = lineno;
|
||||
ellAdd(&mutexList,&pmutexNode->node);
|
||||
epicsMutexOsdUnlock(epicsMutexGlobalLock);
|
||||
return(pmutexNode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
epicsMutexId epicsStdCall epicsMutexOsiMustCreate(
|
||||
const char *pFileName,int lineno)
|
||||
{
|
||||
epicsMutexId id = epicsMutexOsiCreate(pFileName,lineno);
|
||||
assert(id);
|
||||
return(id );
|
||||
if(!id) {
|
||||
cantProceed("epicsMutexOsiMustCreate() fails at %s:%d\n",
|
||||
pFileName, lineno);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
void epicsStdCall epicsMutexDestroy(epicsMutexId pmutexNode)
|
||||
{
|
||||
epicsMutexLockStatus lockStat =
|
||||
epicsMutexOsdLock(epicsMutexGlobalLock);
|
||||
assert ( lockStat == epicsMutexLockOK );
|
||||
ellDelete(&mutexList,&pmutexNode->node);
|
||||
epicsMutexOsdDestroy(pmutexNode->id);
|
||||
VALGRIND_MEMPOOL_FREE(&freeList, pmutexNode);
|
||||
VALGRIND_MEMPOOL_ALLOC(&freeList, &pmutexNode->node, sizeof(pmutexNode->node));
|
||||
ellAdd(&freeList,&pmutexNode->node);
|
||||
epicsMutexOsdUnlock(epicsMutexGlobalLock);
|
||||
}
|
||||
|
||||
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
|
||||
{
|
||||
epicsMutexOsdUnlock(pmutexNode->id);
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsStdCall epicsMutexLock(
|
||||
epicsMutexId pmutexNode)
|
||||
{
|
||||
epicsMutexLockStatus status =
|
||||
epicsMutexOsdLock(pmutexNode->id);
|
||||
# ifdef LOG_LAST_OWNER
|
||||
if ( status == epicsMutexLockOK ) {
|
||||
pmutexNode->lastOwner = epicsThreadGetIdSelf();
|
||||
}
|
||||
# endif
|
||||
return status;
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsStdCall epicsMutexTryLock(
|
||||
epicsMutexId pmutexNode)
|
||||
{
|
||||
epicsMutexLockStatus status =
|
||||
epicsMutexOsdTryLock(pmutexNode->id);
|
||||
# ifdef LOG_LAST_OWNER
|
||||
if ( status == epicsMutexLockOK ) {
|
||||
pmutexNode->lastOwner = epicsThreadGetIdSelf();
|
||||
}
|
||||
# endif
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Empty the freeList.
|
||||
* Called from epicsExit.c, but not via epicsAtExit()
|
||||
* to avoid the possibility of a circular reference.
|
||||
*/
|
||||
extern "C"
|
||||
void epicsMutexCleanup(void)
|
||||
{
|
||||
ELLNODE *cur;
|
||||
epicsMutexLockStatus lockStat =
|
||||
epicsMutexOsdLock(epicsMutexGlobalLock);
|
||||
assert ( lockStat == epicsMutexLockOK );
|
||||
|
||||
while((cur=ellGet(&freeList))!=NULL) {
|
||||
VALGRIND_MEMPOOL_FREE(&freeList, cur);
|
||||
free(cur);
|
||||
if(pmutexNode) {
|
||||
epicsMutexMustLock(&epicsMutexGlobalLock);
|
||||
ellDelete(&mutexList, &pmutexNode->node);
|
||||
(void)epicsMutexUnlock(&epicsMutexGlobalLock);
|
||||
epicsMutexOsdCleanup(pmutexNode);
|
||||
free(pmutexNode);
|
||||
}
|
||||
|
||||
epicsMutexOsdUnlock(epicsMutexGlobalLock);
|
||||
}
|
||||
|
||||
void epicsStdCall epicsMutexShow(
|
||||
epicsMutexId pmutexNode, unsigned int level)
|
||||
{
|
||||
# ifdef LOG_LAST_OWNER
|
||||
char threadName [255];
|
||||
if ( pmutexNode->lastOwner ) {
|
||||
# error currently not safe to fetch name for stale thread
|
||||
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);
|
||||
# else
|
||||
printf("epicsMutexId %p source %s line %d\n",
|
||||
(void *)pmutexNode, pmutexNode->pFileName,
|
||||
pmutexNode->lineno);
|
||||
# endif
|
||||
printf("epicsMutexId %p source %s line %d\n",
|
||||
(void *)pmutexNode, pmutexNode->pFileName,
|
||||
pmutexNode->lineno);
|
||||
if ( level > 0 ) {
|
||||
epicsMutexOsdShow(pmutexNode->id,level-1);
|
||||
epicsMutexOsdShow(pmutexNode,level-1);
|
||||
}
|
||||
}
|
||||
|
||||
void epicsStdCall epicsMutexShowAll(int onlyLocked,unsigned int level)
|
||||
{
|
||||
epicsMutexParm *pmutexNode;
|
||||
epicsMutexOsdSetup();
|
||||
|
||||
if (epicsMutexOsiOnce == EPICS_THREAD_ONCE_INIT)
|
||||
return;
|
||||
|
||||
printf("ellCount(&mutexList) %d ellCount(&freeList) %d\n",
|
||||
ellCount(&mutexList),ellCount(&freeList));
|
||||
printf("ellCount(&mutexList) %d\n", ellCount(&mutexList));
|
||||
epicsMutexOsdShowAll();
|
||||
epicsMutexLockStatus lockStat =
|
||||
epicsMutexOsdLock(epicsMutexGlobalLock);
|
||||
assert ( lockStat == epicsMutexLockOK );
|
||||
pmutexNode = reinterpret_cast < epicsMutexParm * > ( ellFirst(&mutexList) );
|
||||
while(pmutexNode) {
|
||||
epicsMutexMustLock(&epicsMutexGlobalLock);
|
||||
for(ELLNODE *cur =ellFirst(&mutexList); cur; cur = ellNext(cur)) {
|
||||
epicsMutexParm *lock = CONTAINER(cur, epicsMutexParm, node);
|
||||
if(onlyLocked) {
|
||||
epicsMutexLockStatus status;
|
||||
status = epicsMutexOsdTryLock(pmutexNode->id);
|
||||
if(status==epicsMutexLockOK) {
|
||||
epicsMutexOsdUnlock(pmutexNode->id);
|
||||
pmutexNode =
|
||||
reinterpret_cast < epicsMutexParm * >
|
||||
( ellNext(&pmutexNode->node) );
|
||||
continue;
|
||||
// cycle through to test state
|
||||
if(epicsMutexTryLock(lock)==epicsMutexLockOK) {
|
||||
epicsMutexUnlock(lock);
|
||||
continue; // was not locked, skip
|
||||
}
|
||||
}
|
||||
epicsMutexShow(pmutexNode, level);
|
||||
pmutexNode =
|
||||
reinterpret_cast < epicsMutexParm * > ( ellNext(&pmutexNode->node) );
|
||||
epicsMutexShow(lock, level);
|
||||
}
|
||||
epicsMutexOsdUnlock(epicsMutexGlobalLock);
|
||||
epicsMutexUnlock(&epicsMutexGlobalLock);
|
||||
}
|
||||
|
||||
#if !defined(__GNUC__) || __GNUC__<4 || (__GNUC__==4 && __GNUC_MINOR__<8)
|
||||
|
@ -247,21 +247,6 @@ LIBCOM_API void epicsStdCall epicsMutexShow(
|
||||
LIBCOM_API void epicsStdCall epicsMutexShowAll(
|
||||
int onlyLocked,unsigned int level);
|
||||
|
||||
/**@privatesection
|
||||
* The following are interfaces 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 EPICS_PRIVATE_API
|
||||
void epicsMutexOsdShowAll(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
66
modules/libcom/src/osi/epicsMutexImpl.h
Normal file
66
modules/libcom/src/osi/epicsMutexImpl.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* Copyright (c) 2023 Michael Davidsaver
|
||||
* SPDX-License-Identifier: EPICS
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/* Only include from osdMutex.c */
|
||||
|
||||
#ifndef epicsMutexImpl_H
|
||||
#define epicsMutexImpl_H
|
||||
|
||||
#if defined(vxWorks)
|
||||
# include <vxWorks.h>
|
||||
# include <semLib.h>
|
||||
#elif defined(_WIN32)
|
||||
# define VC_EXTRALEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
#elif defined(__rtems__)
|
||||
# include <rtems.h>
|
||||
# include <rtems/score/cpuopts.h>
|
||||
#else
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "ellLib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct epicsMutexParm {
|
||||
/* global list of mutex */
|
||||
ELLNODE node;
|
||||
/* location where mutex was allocated */
|
||||
const char *pFileName;
|
||||
int lineno;
|
||||
#if defined(vxWorks)
|
||||
SEM_ID osd;
|
||||
#elif defined(_WIN32)
|
||||
CRITICAL_SECTION osd;
|
||||
#elif defined(__RTEMS_MAJOR__) && __RTEMS_MAJOR__<5
|
||||
Semaphore_Control *osd;
|
||||
#else
|
||||
pthread_mutex_t osd;
|
||||
#endif
|
||||
};
|
||||
|
||||
void epicsMutexOsdSetup(void);
|
||||
long epicsMutexOsdPrepare(struct epicsMutexParm *);
|
||||
void epicsMutexOsdCleanup(struct epicsMutexParm *);
|
||||
void epicsMutexOsdShow(struct epicsMutexParm *,unsigned int level);
|
||||
void epicsMutexOsdShowAll(void);
|
||||
|
||||
extern struct epicsMutexParm epicsMutexGlobalLock;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C
|
||||
#endif
|
||||
|
||||
#endif // epicsMutexImpl_H
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "epicsEvent.h"
|
||||
#include "epicsThread.h"
|
||||
#include "rtemsNamePvt.h"
|
||||
#include "errlog.h"
|
||||
|
||||
/* #define EPICS_RTEMS_SEMAPHORE_STATS */
|
||||
@ -47,12 +48,9 @@ epicsEventCreate(epicsEventInitialState initialState)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
rtems_id sid;
|
||||
rtems_interrupt_level level;
|
||||
static char c1 = 'a';
|
||||
static char c2 = 'a';
|
||||
static char c3 = 'a';
|
||||
static uint32_t name;
|
||||
|
||||
sc = rtems_semaphore_create (rtems_build_name ('B', c3, c2, c1),
|
||||
sc = rtems_semaphore_create (next_rtems_name ('B', &name),
|
||||
initialState,
|
||||
RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE |
|
||||
RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL,
|
||||
@ -62,26 +60,6 @@ epicsEventCreate(epicsEventInitialState initialState)
|
||||
errlogPrintf ("Can't create binary semaphore: %s\n", rtems_status_text (sc));
|
||||
return NULL;
|
||||
}
|
||||
rtems_interrupt_disable (level);
|
||||
if (c1 == 'z') {
|
||||
if (c2 == 'z') {
|
||||
if (c3 == 'z') {
|
||||
c3 = 'a';
|
||||
}
|
||||
else {
|
||||
c3++;
|
||||
}
|
||||
c2 = 'a';
|
||||
}
|
||||
else {
|
||||
c2++;
|
||||
}
|
||||
c1 = 'a';
|
||||
}
|
||||
else {
|
||||
c1++;
|
||||
}
|
||||
rtems_interrupt_enable (level);
|
||||
return (epicsEventId)sid;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
|
||||
@ -26,97 +27,84 @@
|
||||
|
||||
#include "epicsStdio.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsMutexImpl.h"
|
||||
#include "rtemsNamePvt.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "errlog.h"
|
||||
|
||||
#define RTEMS_FAST_MUTEX
|
||||
/* #define EPICS_RTEMS_SEMAPHORE_STATS */
|
||||
/*
|
||||
* Some performance tuning instrumentation
|
||||
*/
|
||||
#ifdef EPICS_RTEMS_SEMAPHORE_STATS
|
||||
unsigned long semMstat[4];
|
||||
#define SEMSTAT(i) semMstat[i]++;
|
||||
#else
|
||||
#define SEMSTAT(i)
|
||||
#endif
|
||||
uint32_t next_rtems_name(char prefix, uint32_t* counter)
|
||||
{
|
||||
uint32_t next;
|
||||
rtems_interrupt_level level;
|
||||
char a, b, c;
|
||||
|
||||
struct epicsMutexOSD *
|
||||
epicsMutexOsdCreate(void)
|
||||
rtems_interrupt_disable (level);
|
||||
next = *counter;
|
||||
*counter = (next+1)%(26u*26u*26u);
|
||||
rtems_interrupt_enable (level);
|
||||
|
||||
a = 'a' + (next % 26u);
|
||||
next /= 26u;
|
||||
b = 'a' + (next % 26u);
|
||||
next /= 26u;
|
||||
c = 'a' + (next % 26u); // modulo should be redundant, but ... paranoia
|
||||
|
||||
return rtems_build_name(prefix, a, b, c);
|
||||
}
|
||||
|
||||
void epicsMutexOsdSetup(void)
|
||||
{
|
||||
// TODO: use RTEMS_SYSINIT_ITEM() ?
|
||||
if(!epicsMutexGlobalLock.osd) {
|
||||
epicsMutexOsdPrepare(&epicsMutexGlobalLock);
|
||||
}
|
||||
}
|
||||
|
||||
long epicsMutexOsdPrepare(struct epicsMutexParm *mutex)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
rtems_id sid;
|
||||
rtems_interrupt_level level;
|
||||
static char c1 = 'a';
|
||||
static char c2 = 'a';
|
||||
static char c3 = 'a';
|
||||
static uint32_t name;
|
||||
|
||||
sc = rtems_semaphore_create (rtems_build_name ('M', c3, c2, c1),
|
||||
sc = rtems_semaphore_create (next_rtems_name ('M', &name),
|
||||
1,
|
||||
RTEMS_PRIORITY|RTEMS_BINARY_SEMAPHORE|RTEMS_INHERIT_PRIORITY|RTEMS_NO_PRIORITY_CEILING|RTEMS_LOCAL,
|
||||
0,
|
||||
&sid);
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
errlogPrintf ("Can't create mutex semaphore: %s\n", rtems_status_text (sc));
|
||||
return NULL;
|
||||
return ENOMEM;
|
||||
}
|
||||
rtems_interrupt_disable (level);
|
||||
if (c1 == 'z') {
|
||||
if (c2 == 'z') {
|
||||
if (c3 == 'z') {
|
||||
c3 = 'a';
|
||||
}
|
||||
else {
|
||||
c3++;
|
||||
}
|
||||
c2 = 'a';
|
||||
}
|
||||
else {
|
||||
c2++;
|
||||
}
|
||||
c1 = 'a';
|
||||
}
|
||||
else {
|
||||
c1++;
|
||||
}
|
||||
rtems_interrupt_enable (level);
|
||||
#ifdef RTEMS_FAST_MUTEX
|
||||
{
|
||||
Semaphore_Control *the_semaphore;
|
||||
Objects_Locations location;
|
||||
Objects_Locations location;
|
||||
|
||||
the_semaphore = _Semaphore_Get( sid, &location );
|
||||
_Thread_Enable_dispatch();
|
||||
mutex->osd = _Semaphore_Get( sid, &location );
|
||||
_Thread_Enable_dispatch(); /* _Semaphore_Get() disables */
|
||||
|
||||
return (struct epicsMutexOSD *)the_semaphore;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return (struct epicsMutexOSD *)sid;
|
||||
}
|
||||
|
||||
void epicsMutexOsdDestroy(struct epicsMutexOSD * id)
|
||||
void epicsMutexOsdCleanup(struct epicsMutexParm *mutex)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
rtems_id sid;
|
||||
#ifdef RTEMS_FAST_MUTEX
|
||||
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
|
||||
Semaphore_Control *the_semaphore = mutex->osd;
|
||||
sid = the_semaphore->Object.id;
|
||||
#else
|
||||
sid = (rtems_id)id;
|
||||
#endif
|
||||
sc = rtems_semaphore_delete (sid);
|
||||
if (sc == RTEMS_RESOURCE_IN_USE) {
|
||||
rtems_semaphore_release (sid);
|
||||
sc = rtems_semaphore_delete (sid);
|
||||
}
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
errlogPrintf ("Can't destroy semaphore %p (%lx): %s\n", id, (unsigned long)sid, rtems_status_text (sc));
|
||||
errlogPrintf ("Can't destroy semaphore %p (%lx): %s\n",
|
||||
mutex, (unsigned long)sid, rtems_status_text (sc));
|
||||
}
|
||||
|
||||
void epicsMutexOsdUnlock(struct epicsMutexOSD * id)
|
||||
void epicsMutexUnlock(struct epicsMutexParm *mutex)
|
||||
{
|
||||
#ifdef RTEMS_FAST_MUTEX
|
||||
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
|
||||
Semaphore_Control *the_semaphore = mutex->osd;
|
||||
_Thread_Disable_dispatch();
|
||||
_CORE_mutex_Surrender (
|
||||
&the_semaphore->Core_control.mutex,
|
||||
@ -124,18 +112,13 @@ void epicsMutexOsdUnlock(struct epicsMutexOSD * id)
|
||||
NULL
|
||||
);
|
||||
_Thread_Enable_dispatch();
|
||||
#else
|
||||
epicsEventSignal (id);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD * id)
|
||||
epicsMutexLockStatus epicsMutexLock(struct epicsMutexParm *mutex)
|
||||
{
|
||||
#ifdef RTEMS_FAST_MUTEX
|
||||
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
|
||||
Semaphore_Control *the_semaphore = mutex->osd;
|
||||
ISR_Level level;
|
||||
SEMSTAT(0)
|
||||
_ISR_Disable( level );
|
||||
_CORE_mutex_Seize(
|
||||
&the_semaphore->Core_control.mutex,
|
||||
@ -148,19 +131,12 @@ epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD * id)
|
||||
return epicsMutexLockOK;
|
||||
else
|
||||
return epicsMutexLockError;
|
||||
#else
|
||||
SEMSTAT(0)
|
||||
return((epicsEventWait (id) == epicsEventWaitOK)
|
||||
?epicsMutexLockOK : epicsMutexLockError);
|
||||
#endif
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * id)
|
||||
epicsMutexLockStatus epicsMutexTryLock(struct epicsMutexParm *mutex)
|
||||
{
|
||||
#ifdef RTEMS_FAST_MUTEX
|
||||
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
|
||||
Semaphore_Control *the_semaphore = mutex->osd;
|
||||
ISR_Level level;
|
||||
SEMSTAT(2)
|
||||
_ISR_Disable( level );
|
||||
_CORE_mutex_Seize(
|
||||
&the_semaphore->Core_control.mutex,
|
||||
@ -175,25 +151,12 @@ epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * id)
|
||||
return epicsMutexLockTimeout;
|
||||
else
|
||||
return epicsMutexLockError;
|
||||
#else
|
||||
epicsEventWaitStatus status;
|
||||
SEMSTAT(2)
|
||||
status = epicsEventTryWait(id);
|
||||
return((status==epicsEventWaitOK
|
||||
? epicsMutexLockOK
|
||||
: (status==epicsEventWaitTimeout)
|
||||
? epicsMutexLockTimeout
|
||||
: epicsMutexLockError));
|
||||
#endif
|
||||
}
|
||||
|
||||
LIBCOM_API void epicsMutexOsdShow(struct epicsMutexOSD * id,unsigned int level)
|
||||
LIBCOM_API void epicsMutexOsdShow(struct epicsMutexParm *mutex,unsigned int level)
|
||||
{
|
||||
#ifdef RTEMS_FAST_MUTEX
|
||||
Semaphore_Control *the_semaphore = (Semaphore_Control *)id;
|
||||
id = (struct epicsMutexOSD *)the_semaphore->Object.id;
|
||||
#endif
|
||||
epicsEventShow ((epicsEventId)id,level);
|
||||
Semaphore_Control *the_semaphore = mutex->osd;
|
||||
epicsEventShow ((epicsEventId)the_semaphore->Object.id,level);
|
||||
}
|
||||
|
||||
void epicsMutexOsdShowAll(void) {}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "epicsStdio.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsMutexImpl.h"
|
||||
#include "epicsString.h"
|
||||
#include "epicsThread.h"
|
||||
#include "cantProceed.h"
|
||||
@ -59,7 +60,7 @@ struct taskVar {
|
||||
unsigned int threadVariableCapacity;
|
||||
void **threadVariables;
|
||||
};
|
||||
static struct epicsMutexOSD *taskVarMutex;
|
||||
static struct epicsMutexParm taskVarMutex = {ELLNODE_INIT, __FILE__, __LINE__};
|
||||
static struct taskVar *taskVarHead;
|
||||
#define RTEMS_NOTEPAD_TASKVAR 11
|
||||
|
||||
@ -67,15 +68,7 @@ static struct taskVar *taskVarHead;
|
||||
* Support for `once-only' execution
|
||||
*/
|
||||
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");
|
||||
}
|
||||
}
|
||||
static struct epicsMutexParm onceMutex = {ELLNODE_INIT, __FILE__, __LINE__};
|
||||
|
||||
/*
|
||||
* Just map osi 0 to 99 into RTEMS 199 to 100
|
||||
@ -161,13 +154,13 @@ epicsThreadGetStackSize (epicsThreadStackSizeClass size)
|
||||
static void
|
||||
taskVarLock (void)
|
||||
{
|
||||
epicsMutexOsdMustLock (taskVarMutex);
|
||||
epicsMutexMustLock (&taskVarMutex);
|
||||
}
|
||||
|
||||
static void
|
||||
taskVarUnlock (void)
|
||||
{
|
||||
epicsMutexOsdUnlock (taskVarMutex);
|
||||
epicsMutexUnlock (&taskVarMutex);
|
||||
}
|
||||
|
||||
static
|
||||
@ -243,7 +236,7 @@ setThreadInfo(rtems_id tid, const char *name, EPICSTHREADFUNC funptr,
|
||||
v->threadVariables = NULL;
|
||||
v->isRunning = 1;
|
||||
if (joinable) {
|
||||
char c[3];
|
||||
char c[3] = {0,0,0};
|
||||
strncpy(c, v->name, 3);
|
||||
sc = rtems_barrier_create(rtems_build_name('~', c[0], c[1], c[2]),
|
||||
RTEMS_BARRIER_AUTOMATIC_RELEASE | RTEMS_LOCAL,
|
||||
@ -288,10 +281,8 @@ epicsThreadInit (void)
|
||||
rtems_task_priority old;
|
||||
|
||||
rtems_task_set_priority (RTEMS_SELF, epicsThreadGetOssPriorityValue(99), &old);
|
||||
onceMutex = epicsMutexOsdCreate();
|
||||
taskVarMutex = epicsMutexOsdCreate();
|
||||
if (!onceMutex || !taskVarMutex)
|
||||
cantProceed("epicsThreadInit() can't create global mutexes\n");
|
||||
epicsMutexOsdPrepare(&taskVarMutex);
|
||||
epicsMutexOsdPrepare(&onceMutex);
|
||||
rtems_task_ident (RTEMS_SELF, 0, &tid);
|
||||
if(setThreadInfo (tid, "_main_", NULL, NULL, 0) != RTEMS_SUCCESSFUL)
|
||||
cantProceed("epicsThreadInit() unable to setup _main_");
|
||||
@ -317,7 +308,7 @@ epicsThreadCreateOpt (
|
||||
unsigned int stackSize;
|
||||
rtems_id tid;
|
||||
rtems_status_code sc;
|
||||
char c[4];
|
||||
char c[4] = {0,0,0,0};
|
||||
|
||||
if (!initialized)
|
||||
epicsThreadInit();
|
||||
@ -612,26 +603,26 @@ void epicsThreadOnce(epicsThreadOnceId *id, void(*func)(void *), void *arg)
|
||||
#define EPICS_THREAD_ONCE_DONE (epicsThreadId) 1
|
||||
|
||||
if (!initialized) epicsThreadInit();
|
||||
epicsMutexOsdMustLock(onceMutex);
|
||||
epicsMutexMustLock(&onceMutex);
|
||||
if (*id != EPICS_THREAD_ONCE_DONE) {
|
||||
if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
|
||||
*id = epicsThreadGetIdSelf(); /* mark active */
|
||||
epicsMutexOsdUnlock(onceMutex);
|
||||
epicsMutexUnlock(&onceMutex);
|
||||
func(arg);
|
||||
epicsMutexOsdMustLock(onceMutex);
|
||||
epicsMutexMustLock(&onceMutex);
|
||||
*id = EPICS_THREAD_ONCE_DONE; /* mark done */
|
||||
} else if (*id == epicsThreadGetIdSelf()) {
|
||||
epicsMutexOsdUnlock(onceMutex);
|
||||
epicsMutexUnlock(&onceMutex);
|
||||
cantProceed("Recursive epicsThreadOnce() initialization\n");
|
||||
} else
|
||||
while (*id != EPICS_THREAD_ONCE_DONE) {
|
||||
/* Another thread is in the above func(arg) call. */
|
||||
epicsMutexOsdUnlock(onceMutex);
|
||||
epicsMutexUnlock(&onceMutex);
|
||||
epicsThreadSleep(epicsThreadSleepQuantum());
|
||||
epicsMutexOsdMustLock(onceMutex);
|
||||
epicsMutexMustLock(&onceMutex);
|
||||
}
|
||||
}
|
||||
epicsMutexOsdUnlock(onceMutex);
|
||||
epicsMutexUnlock(&onceMutex);
|
||||
}
|
||||
|
||||
/*
|
||||
|
20
modules/libcom/src/osi/os/RTEMS-score/rtemsNamePvt.h
Normal file
20
modules/libcom/src/osi/os/RTEMS-score/rtemsNamePvt.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2023 Michael Davidsaver
|
||||
* SPDX-License-Identifier: EPICS
|
||||
* EPICS Base is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef RTEMSNAMEPVT_H
|
||||
#define RTEMSNAMEPVT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Compute rtems_build_name(prefix, A, B, C) where A, B, C are the letters a-z.
|
||||
* eg. "Qaaa"
|
||||
*
|
||||
* 'counter' is incremented atomically during each call.
|
||||
*/
|
||||
uint32_t next_rtems_name(char prefix, uint32_t* counter);
|
||||
|
||||
#endif // RTEMSNAMEPVT_H
|
@ -20,147 +20,59 @@
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define VC_EXTRALEAN
|
||||
#define STRICT
|
||||
#include <windows.h>
|
||||
#if _WIN32_WINNT < 0x0501
|
||||
# error Minimum supported is Windows XP
|
||||
#endif
|
||||
|
||||
#define EPICS_PRIVATE_API
|
||||
|
||||
#include "libComAPI.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsMutexImpl.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "epicsStdio.h"
|
||||
|
||||
typedef struct epicsMutexOSD {
|
||||
union {
|
||||
HANDLE mutex;
|
||||
CRITICAL_SECTION criticalSection;
|
||||
} os;
|
||||
} epicsMutexOSD;
|
||||
|
||||
static BOOL thisIsNT = FALSE;
|
||||
static LONG weHaveInitialized = 0;
|
||||
|
||||
/*
|
||||
* epicsMutexCreate ()
|
||||
*/
|
||||
epicsMutexOSD * epicsMutexOsdCreate ( void )
|
||||
static epicsThreadOnceId epicsMutexOsdOnce = EPICS_THREAD_ONCE_INIT;
|
||||
static void epicsMutexOsdInit(void* unused)
|
||||
{
|
||||
epicsMutexOSD * pSem;
|
||||
|
||||
if ( ! weHaveInitialized ) {
|
||||
BOOL status;
|
||||
OSVERSIONINFO osInfo;
|
||||
osInfo.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO );
|
||||
status = GetVersionEx ( & osInfo );
|
||||
thisIsNT = status && ( osInfo.dwPlatformId == VER_PLATFORM_WIN32_NT );
|
||||
weHaveInitialized = 1;
|
||||
}
|
||||
|
||||
pSem = malloc ( sizeof (*pSem) );
|
||||
if ( pSem ) {
|
||||
if ( thisIsNT ) {
|
||||
InitializeCriticalSection ( &pSem->os.criticalSection );
|
||||
}
|
||||
else {
|
||||
pSem->os.mutex = CreateMutex ( NULL, FALSE, NULL );
|
||||
if ( pSem->os.mutex == 0 ) {
|
||||
free ( pSem );
|
||||
pSem = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pSem;
|
||||
(void)unused;
|
||||
InitializeCriticalSection(&epicsMutexGlobalLock.osd);
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsMutexOsdDestroy ()
|
||||
*/
|
||||
void epicsMutexOsdDestroy ( epicsMutexOSD * pSem )
|
||||
void epicsMutexOsdSetup()
|
||||
{
|
||||
if ( thisIsNT ) {
|
||||
DeleteCriticalSection ( &pSem->os.criticalSection );
|
||||
}
|
||||
else {
|
||||
CloseHandle ( pSem->os.mutex );
|
||||
}
|
||||
free ( pSem );
|
||||
epicsThreadOnce(&epicsMutexOsdOnce, &epicsMutexOsdInit, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsMutexOsdUnlock ()
|
||||
*/
|
||||
void epicsMutexOsdUnlock ( epicsMutexOSD * pSem )
|
||||
long epicsMutexOsdPrepare(struct epicsMutexParm *mutex)
|
||||
{
|
||||
if ( thisIsNT ) {
|
||||
LeaveCriticalSection ( &pSem->os.criticalSection );
|
||||
}
|
||||
else {
|
||||
BOOL success = ReleaseMutex ( pSem->os.mutex );
|
||||
assert ( success );
|
||||
}
|
||||
InitializeCriticalSection(&mutex->osd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsMutexOsdLock ()
|
||||
*/
|
||||
epicsMutexLockStatus epicsMutexOsdLock ( epicsMutexOSD * pSem )
|
||||
void epicsMutexOsdCleanup(struct epicsMutexParm *mutex)
|
||||
{
|
||||
if ( thisIsNT ) {
|
||||
EnterCriticalSection ( &pSem->os.criticalSection );
|
||||
}
|
||||
else {
|
||||
DWORD status = WaitForSingleObject ( pSem->os.mutex, INFINITE );
|
||||
if ( status != WAIT_OBJECT_0 ) {
|
||||
return epicsMutexLockError;
|
||||
}
|
||||
}
|
||||
DeleteCriticalSection(&mutex->osd);
|
||||
}
|
||||
|
||||
void epicsStdCall epicsMutexUnlock ( struct epicsMutexParm *mutex )
|
||||
{
|
||||
LeaveCriticalSection ( &mutex->osd );
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsStdCall epicsMutexLock ( struct epicsMutexParm *mutex )
|
||||
{
|
||||
EnterCriticalSection ( &mutex->osd );
|
||||
return epicsMutexLockOK;
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsMutexOsdTryLock ()
|
||||
*/
|
||||
epicsMutexLockStatus epicsMutexOsdTryLock ( epicsMutexOSD * pSem )
|
||||
epicsMutexLockStatus epicsStdCall epicsMutexTryLock ( struct epicsMutexParm *mutex )
|
||||
{
|
||||
if ( thisIsNT ) {
|
||||
if ( TryEnterCriticalSection ( &pSem->os.criticalSection ) ) {
|
||||
return epicsMutexLockOK;
|
||||
}
|
||||
else {
|
||||
return epicsMutexLockTimeout;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DWORD status = WaitForSingleObject ( pSem->os.mutex, 0 );
|
||||
if ( status != WAIT_OBJECT_0 ) {
|
||||
if (status == WAIT_TIMEOUT) {
|
||||
return epicsMutexLockTimeout;
|
||||
}
|
||||
else {
|
||||
return epicsMutexLockError;
|
||||
}
|
||||
}
|
||||
}
|
||||
return epicsMutexLockOK;
|
||||
return TryEnterCriticalSection ( &mutex->osd ) ? epicsMutexLockOK : epicsMutexLockTimeout;
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsMutexOsdShow ()
|
||||
*/
|
||||
void epicsMutexOsdShow ( epicsMutexOSD * pSem, unsigned level )
|
||||
void epicsMutexOsdShow ( struct epicsMutexParm *mutex, unsigned level )
|
||||
{
|
||||
if ( thisIsNT ) {
|
||||
printf ("epicsMutex: win32 critical section at %p\n",
|
||||
(void * ) & pSem->os.criticalSection );
|
||||
}
|
||||
else {
|
||||
printf ( "epicsMutex: win32 mutex at %p\n",
|
||||
( void * ) pSem->os.mutex );
|
||||
}
|
||||
(void)level;
|
||||
printf ("epicsMutex: win32 critical section at %p\n",
|
||||
(void * ) & mutex->osd );
|
||||
}
|
||||
|
||||
void epicsMutexOsdShowAll(void) {}
|
||||
|
@ -25,14 +25,15 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#define EPICS_PRIVATE_API
|
||||
#define epicsStdioStdStreams
|
||||
#define epicsStdioStdPrintfEtc
|
||||
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsMutexImpl.h"
|
||||
#include "osdPosixMutexPriv.h"
|
||||
#include "cantProceed.h"
|
||||
#include "epicsTime.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsStdio.h"
|
||||
#include "epicsAssert.h"
|
||||
|
||||
#define checkStatus(status,message) \
|
||||
if((status)) { \
|
||||
@ -119,62 +120,62 @@ static int mutexLock(pthread_mutex_t *id)
|
||||
return status;
|
||||
}
|
||||
|
||||
typedef struct epicsMutexOSD {
|
||||
pthread_mutex_t lock;
|
||||
} epicsMutexOSD;
|
||||
/* used if OS does not support statically allocated mutex */
|
||||
static pthread_once_t epicsMutexOsdOnce = PTHREAD_ONCE_INIT;
|
||||
|
||||
epicsMutexOSD * epicsMutexOsdCreate(void) {
|
||||
epicsMutexOSD *pmutex;
|
||||
int status;
|
||||
|
||||
pmutex = calloc(1, sizeof(*pmutex));
|
||||
if(!pmutex)
|
||||
return NULL;
|
||||
|
||||
status = osdPosixMutexInit(&pmutex->lock, PTHREAD_MUTEX_RECURSIVE);
|
||||
if (!status)
|
||||
return pmutex;
|
||||
|
||||
free(pmutex);
|
||||
return NULL;
|
||||
static void epicsMutexOsdInit(void)
|
||||
{
|
||||
int ret = pthread_mutex_init(&epicsMutexGlobalLock.osd, NULL);
|
||||
if(ret) {
|
||||
/* something has gone wrong early. Not much can be done...*/
|
||||
fprintf(stderr, "osdMutex early init failure %d.\n", ret);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void epicsMutexOsdDestroy(struct epicsMutexOSD * pmutex)
|
||||
void epicsMutexOsdSetup()
|
||||
{
|
||||
int status;
|
||||
int ret = pthread_once(&epicsMutexOsdOnce, &epicsMutexOsdInit);
|
||||
if(ret) {
|
||||
/* ditto...*/
|
||||
fprintf(stderr, "osdMutex early once failure %d.\n", ret);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
status = pthread_mutex_destroy(&pmutex->lock);
|
||||
long epicsMutexOsdPrepare(struct epicsMutexParm *pmutex) {
|
||||
return osdPosixMutexInit(&pmutex->osd, PTHREAD_MUTEX_RECURSIVE);
|
||||
}
|
||||
|
||||
void epicsMutexOsdCleanup(struct epicsMutexParm *pmutex)
|
||||
{
|
||||
int status = pthread_mutex_destroy(&pmutex->osd);
|
||||
checkStatus(status, "pthread_mutex_destroy");
|
||||
free(pmutex);
|
||||
}
|
||||
|
||||
void epicsMutexOsdUnlock(struct epicsMutexOSD * pmutex)
|
||||
void epicsMutexUnlock(struct epicsMutexParm * pmutex)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = pthread_mutex_unlock(&pmutex->lock);
|
||||
int status = pthread_mutex_unlock(&pmutex->osd);
|
||||
checkStatus(status, "pthread_mutex_unlock epicsMutexOsdUnlock");
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD * pmutex)
|
||||
epicsMutexLockStatus epicsMutexLock(struct epicsMutexParm * pmutex)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = mutexLock(&pmutex->lock);
|
||||
int status = mutexLock(&pmutex->osd);
|
||||
if (status == EINVAL) return epicsMutexLockError;
|
||||
if(status) {
|
||||
errlogMessage("epicsMutex pthread_mutex_lock failed: error epicsMutexOsdLock\n");
|
||||
errlogMessage("epicsMutex pthread_mutex_lock failed: error epicsMutexLock\n");
|
||||
return epicsMutexLockError;
|
||||
}
|
||||
return epicsMutexLockOK;
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * pmutex)
|
||||
epicsMutexLockStatus epicsMutexTryLock(struct epicsMutexParm * pmutex)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!pmutex) return epicsMutexLockError;
|
||||
status = pthread_mutex_trylock(&pmutex->lock);
|
||||
status = pthread_mutex_trylock(&pmutex->osd);
|
||||
if (status == EINVAL) return epicsMutexLockError;
|
||||
if (status == EBUSY) return epicsMutexLockTimeout;
|
||||
if(status) {
|
||||
@ -184,12 +185,13 @@ epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * pmutex)
|
||||
return epicsMutexLockOK;
|
||||
}
|
||||
|
||||
void epicsMutexOsdShow(struct epicsMutexOSD * pmutex, unsigned int level)
|
||||
void epicsMutexOsdShow(struct epicsMutexParm * pmutex, unsigned int level)
|
||||
{
|
||||
(void)level;
|
||||
/* GLIBC w/ NTPL is passing the &lock.__data.__lock as the first argument (UADDR)
|
||||
* of the futex() syscall. __lock is at offset 0 of the enclosing structures.
|
||||
*/
|
||||
printf(" pthread_mutex_t* uaddr=%p\n", &pmutex->lock);
|
||||
epicsStdoutPrintf(" pthread_mutex_t* uaddr=%p\n", &pmutex->osd);
|
||||
}
|
||||
|
||||
void epicsMutexOsdShowAll(void)
|
||||
@ -198,11 +200,11 @@ void epicsMutexOsdShowAll(void)
|
||||
int proto = -1;
|
||||
int ret = pthread_mutexattr_getprotocol(&globalAttrRecursive, &proto);
|
||||
if(ret) {
|
||||
printf("PI maybe not enabled: %d\n", ret);
|
||||
epicsStdoutPrintf("PI maybe not enabled: %d\n", ret);
|
||||
} else {
|
||||
printf("PI is%s enabled\n", proto==PTHREAD_PRIO_INHERIT ? "" : " not");
|
||||
epicsStdoutPrintf("PI is%s enabled\n", proto==PTHREAD_PRIO_INHERIT ? "" : " not");
|
||||
}
|
||||
#else
|
||||
printf("PI not supported\n");
|
||||
epicsStdoutPrintf("PI not supported\n");
|
||||
#endif
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <semLib.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <objLib.h>
|
||||
#include <sysLib.h>
|
||||
@ -23,30 +24,47 @@ int sysClkRateGet(void);
|
||||
#define EPICS_PRIVATE_API
|
||||
|
||||
#include "epicsMutex.h"
|
||||
|
||||
struct epicsMutexOSD * epicsMutexOsdCreate(void)
|
||||
#include "epicsMutexImpl.h"
|
||||
|
||||
void epicsMutexOsdSetup(void)
|
||||
{
|
||||
return((struct epicsMutexOSD *)
|
||||
semMCreate(SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY));
|
||||
if(!epicsMutexGlobalLock.osd) {
|
||||
epicsMutexOsdPrepare(&epicsMutexGlobalLock);
|
||||
}
|
||||
}
|
||||
|
||||
void epicsMutexOsdDestroy(struct epicsMutexOSD * id)
|
||||
long epicsMutexOsdPrepare(struct epicsMutexParm *mutex)
|
||||
{
|
||||
semDelete((SEM_ID)id);
|
||||
mutex->osd = semMCreate(SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY);
|
||||
return mutex->osd ? 0 : ENOMEM;
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * id)
|
||||
void epicsMutexOsdCleanup(struct epicsMutexParm *mutex)
|
||||
{
|
||||
int status;
|
||||
status = semTake((SEM_ID)id,NO_WAIT);
|
||||
semDelete(mutex->osd);
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexLock(struct epicsMutexParm *mutex)
|
||||
{
|
||||
return semTake(mutex->osd,WAIT_FOREVER)==OK ? epicsMutexLockOK : epicsMutexLockError;
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexTryLock(struct epicsMutexParm *mutex)
|
||||
{
|
||||
int status = semTake(mutex->osd,NO_WAIT);
|
||||
if(status==OK) return(epicsMutexLockOK);
|
||||
if(errno==S_objLib_OBJ_UNAVAILABLE) return(epicsMutexLockTimeout);
|
||||
return(epicsMutexLockError);
|
||||
}
|
||||
|
||||
void epicsMutexOsdShow(struct epicsMutexOSD * id,unsigned int level)
|
||||
void epicsMutexUnlock(struct epicsMutexParm *mutex)
|
||||
{
|
||||
semShow((SEM_ID)id,level);
|
||||
semGive(mutex->osd);
|
||||
}
|
||||
|
||||
void epicsMutexOsdShow(struct epicsMutexParm *mutex,unsigned int level)
|
||||
{
|
||||
semShow(mutex->osd,level);
|
||||
}
|
||||
|
||||
void epicsMutexOsdShowAll(void) {}
|
||||
|
@ -13,13 +13,3 @@
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <semLib.h>
|
||||
|
||||
/* If the macro is replaced by inline it is necessary to say
|
||||
static __inline__
|
||||
but then a warning message appears everywhere osdMutex.h is included
|
||||
*/
|
||||
|
||||
#define epicsMutexOsdUnlock(ID) semGive((SEM_ID)(ID))
|
||||
|
||||
#define epicsMutexOsdLock(ID) \
|
||||
(semTake((SEM_ID)(ID),WAIT_FOREVER)==OK ? epicsMutexLockOK : epicsMutexLockError)
|
||||
|
Reference in New Issue
Block a user