Got epicsSpin from EPICS 7.0 for use in in ring buffers
This commit is contained in:
@@ -18,6 +18,7 @@ epicsReadline_INCLUDES += $(INCLUDES_$(COMMANDLINE_LIBRARY))
|
||||
#POSIX thread priority scheduling flag
|
||||
THREAD_CPPFLAGS_NO += -DDONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING
|
||||
osdThread_CPPFLAGS += $(THREAD_CPPFLAGS_$(USE_POSIX_THREAD_PRIORITY_SCHEDULING))
|
||||
osdSpin_CPPFLAGS += $(THREAD_CPPFLAGS_$(USE_POSIX_THREAD_PRIORITY_SCHEDULING))
|
||||
|
||||
#epicsVersion is created by this Makefile
|
||||
INC += epicsVersion.h
|
||||
@@ -160,6 +161,7 @@ INC += osdInterrupt.h
|
||||
|
||||
INC += epicsMutex.h
|
||||
INC += osdMutex.h
|
||||
INC += epicsSpin.h
|
||||
INC += epicsEvent.h
|
||||
INC += osdEvent.h
|
||||
INC += epicsMath.h
|
||||
@@ -224,6 +226,7 @@ SRCS += osdStdio.c
|
||||
|
||||
SRCS += osdThread.c
|
||||
SRCS += osdMutex.c
|
||||
SRCS += osdSpin.c
|
||||
SRCS += osdEvent.c
|
||||
SRCS += osdTime.cpp
|
||||
SRCS += osdProcess.c
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2012 Helmholtz-Zentrum Berlin
|
||||
* fuer Materialien und Energie GmbH.
|
||||
* Copyright (c) 2012 ITER Organization.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef epicsSpinh
|
||||
#define epicsSpinh
|
||||
|
||||
#include "shareLib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct epicsSpin *epicsSpinId;
|
||||
|
||||
epicsShareFunc epicsSpinId epicsSpinCreate(void);
|
||||
epicsShareFunc epicsSpinId epicsSpinMustCreate(void);
|
||||
epicsShareFunc void epicsSpinDestroy(epicsSpinId);
|
||||
|
||||
epicsShareFunc void epicsSpinLock(epicsSpinId);
|
||||
epicsShareFunc int epicsSpinTryLock(epicsSpinId);
|
||||
epicsShareFunc void epicsSpinUnlock(epicsSpinId);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* epicsSpinh */
|
||||
@@ -0,0 +1,106 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2012 Helmholtz-Zentrum Berlin
|
||||
* fuer Materialien und Energie GmbH.
|
||||
* Copyright (c) 2012 ITER Organization.
|
||||
* Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2013 Brookhaven Science Assoc. as Operator of Brookhaven
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors: Ralph Lange <Ralph.Lange@gmx.de>
|
||||
* Andrew Johnson <anj@aps.anl.gov>
|
||||
* Michael Davidsaver <mdavidsaver@bnl.gov>
|
||||
*
|
||||
* Inspired by Linux UP spinlocks implemention
|
||||
* include/linux/spinlock_api_up.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* RTEMS (single CPU): LOCK INTERRUPT and DISABLE PREEMPTION
|
||||
*
|
||||
* CAVEAT:
|
||||
* This implementation is intended for UP architectures only.
|
||||
*/
|
||||
|
||||
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <rtems.h>
|
||||
|
||||
#include "cantProceed.h"
|
||||
#include "epicsSpin.h"
|
||||
|
||||
typedef struct epicsSpin {
|
||||
rtems_interrupt_level level;
|
||||
unsigned int locked;
|
||||
} epicsSpin;
|
||||
|
||||
epicsSpinId epicsSpinCreate(void) {
|
||||
return calloc(1, sizeof(epicsSpin));
|
||||
}
|
||||
|
||||
epicsSpinId epicsSpinMustCreate(void)
|
||||
{
|
||||
epicsSpinId ret = epicsSpinCreate();
|
||||
if (!ret)
|
||||
cantProceed("epicsSpinMustCreate: epicsSpinCreate failed.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void epicsSpinDestroy(epicsSpinId spin) {
|
||||
free(spin);
|
||||
}
|
||||
|
||||
void epicsSpinLock(epicsSpinId spin) {
|
||||
rtems_interrupt_level level;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
_Thread_Disable_dispatch();
|
||||
if (spin->locked) {
|
||||
rtems_interrupt_enable(level);
|
||||
_Thread_Enable_dispatch();
|
||||
if (!rtems_interrupt_is_in_progress()) {
|
||||
printk("epicsSpinLock(%p): Deadlock.\n", spin);
|
||||
cantProceed("Recursive lock, missed unlock or block when locked.");
|
||||
}
|
||||
else {
|
||||
printk("epicsSpinLock(%p): Deadlock in ISR.\n"
|
||||
"Recursive lock, missed unlock or block when locked.\n",
|
||||
spin);
|
||||
}
|
||||
return;
|
||||
}
|
||||
spin->level = level;
|
||||
spin->locked = 1;
|
||||
}
|
||||
|
||||
int epicsSpinTryLock(epicsSpinId spin) {
|
||||
rtems_interrupt_level level;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
_Thread_Disable_dispatch();
|
||||
if (spin->locked) {
|
||||
rtems_interrupt_enable(level);
|
||||
_Thread_Enable_dispatch();
|
||||
return 1;
|
||||
}
|
||||
spin->level = level;
|
||||
spin->locked = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void epicsSpinUnlock(epicsSpinId spin) {
|
||||
rtems_interrupt_level level = spin->level;
|
||||
|
||||
if (!spin->locked) {
|
||||
printk("epicsSpinUnlock(%p): not locked\n", spin);
|
||||
return;
|
||||
}
|
||||
spin->level = spin->locked = 0;
|
||||
rtems_interrupt_enable (level);
|
||||
_Thread_Enable_dispatch();
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2012 Helmholtz-Zentrum Berlin
|
||||
* fuer Materialien und Energie GmbH.
|
||||
* Copyright (c) 2012 ITER Organization.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* Author: Ralph Lange <Ralph.Lange@gmx.de>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "cantProceed.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsSpin.h"
|
||||
|
||||
/*
|
||||
* Default: EPICS MUTEX IMPLEMENTATION
|
||||
*/
|
||||
|
||||
typedef struct epicsSpin {
|
||||
epicsMutexId lock;
|
||||
} epicsSpin;
|
||||
|
||||
epicsSpinId epicsSpinCreate(void) {
|
||||
epicsSpin *spin;
|
||||
|
||||
spin = calloc(1, sizeof(*spin));
|
||||
if (!spin)
|
||||
goto fail;
|
||||
|
||||
spin->lock = epicsMutexCreate();
|
||||
if (!spin->lock)
|
||||
goto fail;
|
||||
|
||||
return spin;
|
||||
|
||||
fail:
|
||||
free(spin);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
epicsSpinId epicsSpinMustCreate(void)
|
||||
{
|
||||
epicsSpinId ret = epicsSpinCreate();
|
||||
if(!ret)
|
||||
cantProceed("epicsSpinMustCreate: epicsSpinCreate failed.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void epicsSpinDestroy(epicsSpinId spin) {
|
||||
epicsMutexDestroy(spin->lock);
|
||||
free(spin);
|
||||
}
|
||||
|
||||
void epicsSpinLock(epicsSpinId spin) {
|
||||
epicsMutexLockStatus status;
|
||||
|
||||
status = epicsMutexLock(spin->lock);
|
||||
if (status != epicsMutexLockOK) {
|
||||
errlogPrintf("epicsSpinLock(%p): epicsMutexLock returned %s\n", spin,
|
||||
status == epicsMutexLockTimeout ?
|
||||
"epicsMutexLockTimeout" : "epicsMutexLockError");
|
||||
}
|
||||
}
|
||||
|
||||
int epicsSpinTryLock(epicsSpinId spin) {
|
||||
epicsMutexLockStatus status;
|
||||
|
||||
status = epicsMutexTryLock(spin->lock);
|
||||
if (status == epicsMutexLockOK) return 0;
|
||||
if (status == epicsMutexLockTimeout) return 1;
|
||||
|
||||
errlogPrintf("epicsSpinTryLock(%p): epicsMutexTryLock returned epicsMutexLockError\n", spin);
|
||||
return 2;
|
||||
}
|
||||
|
||||
void epicsSpinUnlock(epicsSpinId spin) {
|
||||
epicsMutexUnlock(spin->lock);
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2012 Helmholtz-Zentrum Berlin
|
||||
* fuer Materialien und Energie GmbH.
|
||||
* Copyright (c) 2012 ITER Organization.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* Author: Ralph Lange <Ralph.Lange@gmx.de>
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "errlog.h"
|
||||
#include "cantProceed.h"
|
||||
#include "epicsSpin.h"
|
||||
|
||||
/* POSIX spinlocks may be subject to priority inversion
|
||||
* and so can't be guaranteed safe in situations where
|
||||
* threads have different priorities, and thread
|
||||
* preemption can't be disabled.
|
||||
*/
|
||||
#if defined(DONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING)
|
||||
#if defined(_POSIX_SPIN_LOCKS) && (_POSIX_SPIN_LOCKS > 0)
|
||||
# define USE_PSPIN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define checkStatus(status,message) \
|
||||
if ((status)) { \
|
||||
errlogPrintf("epicsSpin %s failed: error %s\n", \
|
||||
(message), strerror((status))); \
|
||||
}
|
||||
|
||||
#ifdef USE_PSPIN
|
||||
|
||||
/*
|
||||
* POSIX SPIN LOCKS IMPLEMENTATION
|
||||
*/
|
||||
|
||||
typedef struct epicsSpin {
|
||||
pthread_spinlock_t lock;
|
||||
} epicsSpin;
|
||||
|
||||
epicsSpinId epicsSpinCreate(void) {
|
||||
epicsSpin *spin;
|
||||
int status;
|
||||
|
||||
spin = calloc(1, sizeof(*spin));
|
||||
if (!spin)
|
||||
goto fail;
|
||||
|
||||
status = pthread_spin_init(&spin->lock, PTHREAD_PROCESS_PRIVATE);
|
||||
checkStatus(status, "pthread_spin_init");
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
return spin;
|
||||
|
||||
fail:
|
||||
free(spin);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void epicsSpinDestroy(epicsSpinId spin) {
|
||||
int status;
|
||||
|
||||
status = pthread_spin_destroy(&spin->lock);
|
||||
checkStatus(status, "pthread_spin_destroy");
|
||||
|
||||
free(spin);
|
||||
}
|
||||
|
||||
void epicsSpinLock(epicsSpinId spin) {
|
||||
int status;
|
||||
|
||||
status = pthread_spin_lock(&spin->lock);
|
||||
checkStatus(status, "pthread_spin_lock");
|
||||
if (status)
|
||||
cantProceed(NULL);
|
||||
}
|
||||
|
||||
int epicsSpinTryLock(epicsSpinId spin) {
|
||||
int status;
|
||||
|
||||
status = pthread_spin_trylock(&spin->lock);
|
||||
if (status == EBUSY)
|
||||
return 1;
|
||||
checkStatus(status, "pthread_spin_trylock");
|
||||
return status;
|
||||
}
|
||||
|
||||
void epicsSpinUnlock(epicsSpinId spin) {
|
||||
int status;
|
||||
|
||||
status = pthread_spin_unlock(&spin->lock);
|
||||
checkStatus(status, "pthread_spin_unlock");
|
||||
}
|
||||
|
||||
#else /* USE_PSPIN */
|
||||
|
||||
/*
|
||||
* POSIX MUTEX IMPLEMENTATION
|
||||
*/
|
||||
|
||||
typedef struct epicsSpin {
|
||||
pthread_mutex_t lock;
|
||||
} epicsSpin;
|
||||
|
||||
epicsSpinId epicsSpinCreate(void) {
|
||||
epicsSpin *spin;
|
||||
int status;
|
||||
|
||||
spin = calloc(1, sizeof(*spin));
|
||||
if (!spin)
|
||||
goto fail;
|
||||
|
||||
status = pthread_mutex_init(&spin->lock, NULL);
|
||||
checkStatus(status, "pthread_mutex_init");
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
return spin;
|
||||
|
||||
fail:
|
||||
free(spin);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void epicsSpinDestroy(epicsSpinId spin) {
|
||||
int status;
|
||||
|
||||
status = pthread_mutex_destroy(&spin->lock);
|
||||
checkStatus(status, "pthread_mutex_destroy");
|
||||
|
||||
free(spin);
|
||||
}
|
||||
|
||||
void epicsSpinLock(epicsSpinId spin) {
|
||||
int status;
|
||||
|
||||
status = pthread_mutex_lock(&spin->lock);
|
||||
checkStatus(status, "pthread_mutex_lock");
|
||||
if (status)
|
||||
cantProceed(NULL);
|
||||
}
|
||||
|
||||
int epicsSpinTryLock(epicsSpinId spin) {
|
||||
int status;
|
||||
|
||||
status = pthread_mutex_trylock(&spin->lock);
|
||||
if (status == EBUSY)
|
||||
return 1;
|
||||
checkStatus(status, "pthread_mutex_trylock");
|
||||
return status;
|
||||
}
|
||||
|
||||
void epicsSpinUnlock(epicsSpinId spin) {
|
||||
int status;
|
||||
|
||||
status = pthread_mutex_unlock(&spin->lock);
|
||||
checkStatus(status, "pthread_mutex_unlock");
|
||||
}
|
||||
|
||||
#endif /* USE_PSPIN */
|
||||
|
||||
|
||||
epicsSpinId epicsSpinMustCreate(void)
|
||||
{
|
||||
epicsSpinId ret = epicsSpinCreate();
|
||||
if(!ret)
|
||||
cantProceed("epicsSpinMustCreate: epicsSpinCreate failed.");
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2012 Helmholtz-Zentrum Berlin
|
||||
* fuer Materialien und Energie GmbH.
|
||||
* Copyright (c) 2012 ITER Organization.
|
||||
* Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2013 Brookhaven Science Assoc. as Operator of Brookhaven
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors: Ralph Lange <Ralph.Lange@gmx.de>
|
||||
* Andrew Johnson <anj@aps.anl.gov>
|
||||
* Michael Davidsaver <mdavidsaver@bnl.gov>
|
||||
*
|
||||
* Inspired by Linux UP spinlocks implemention
|
||||
* include/linux/spinlock_api_up.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* vxWorks (single CPU): LOCK INTERRUPT and DISABLE PREEMPTION
|
||||
*
|
||||
* CAVEAT:
|
||||
* This implementation will not compile on vxWorks SMP architectures.
|
||||
* These architectures provide spinlocks, which must be used instead.
|
||||
*
|
||||
*/
|
||||
|
||||
/* This is needed for vxWorks 6.x to prevent an obnoxious compiler warning */
|
||||
#define _VSB_CONFIG_FILE <../lib/h/config/vsbConfig.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <intLib.h>
|
||||
#include <logLib.h>
|
||||
#include <taskLib.h>
|
||||
|
||||
#include "cantProceed.h"
|
||||
#include "epicsSpin.h"
|
||||
|
||||
typedef struct epicsSpin {
|
||||
int key;
|
||||
unsigned int locked;
|
||||
} epicsSpin;
|
||||
|
||||
epicsSpinId epicsSpinCreate(void) {
|
||||
return calloc(1, sizeof(epicsSpin));
|
||||
}
|
||||
|
||||
epicsSpinId epicsSpinMustCreate(void)
|
||||
{
|
||||
epicsSpinId ret = epicsSpinCreate();
|
||||
if (!ret)
|
||||
cantProceed("epicsSpinMustCreate: epicsSpinCreate failed.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void epicsSpinDestroy(epicsSpinId spin) {
|
||||
free(spin);
|
||||
}
|
||||
|
||||
void epicsSpinLock(epicsSpinId spin) {
|
||||
int key = intLock();
|
||||
|
||||
if (!intContext())
|
||||
taskLock();
|
||||
if (spin->locked) {
|
||||
intUnlock(key);
|
||||
if (!intContext()) {
|
||||
taskUnlock();
|
||||
logMsg("epicsSpinLock(%p): Deadlock.\n",
|
||||
(int) spin, 0, 0, 0, 0, 0);
|
||||
cantProceed("Recursive lock, missed unlock or block when locked.");
|
||||
}
|
||||
else {
|
||||
logMsg("epicsSpinLock(%p): Deadlock in ISR.\n"
|
||||
"Recursive lock, missed unlock or block when locked.\n",
|
||||
(int) spin, 0, 0, 0, 0, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
spin->key = key;
|
||||
spin->locked = 1;
|
||||
}
|
||||
|
||||
int epicsSpinTryLock(epicsSpinId spin) {
|
||||
int key = intLock();
|
||||
|
||||
if (!intContext())
|
||||
taskLock();
|
||||
if (spin->locked) {
|
||||
intUnlock(key);
|
||||
if (!intContext())
|
||||
taskUnlock();
|
||||
return 1;
|
||||
}
|
||||
spin->key = key;
|
||||
spin->locked = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void epicsSpinUnlock(epicsSpinId spin) {
|
||||
int key = spin->key;
|
||||
|
||||
if (!spin->locked) {
|
||||
logMsg("epicsSpinUnlock(%p): not locked\n",
|
||||
(int) spin, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
spin->key = spin->locked = 0;
|
||||
intUnlock(key);
|
||||
if (!intContext())
|
||||
taskUnlock();
|
||||
}
|
||||
Reference in New Issue
Block a user