libCom/osi: add epicsSpin with default, posix, and vxWorks implementations
- posix uses pthread_spin_ interface when supported, pthread_mutex_ otherwise - default uses epicsMutex - vxWorks (single core) uses intLock()
This commit is contained in:
@@ -20,6 +20,7 @@ INC += osdInterrupt.h
|
||||
|
||||
INC += epicsMutex.h
|
||||
INC += osdMutex.h
|
||||
INC += epicsSpin.h
|
||||
INC += epicsEvent.h
|
||||
INC += osdEvent.h
|
||||
INC += epicsMath.h
|
||||
@@ -107,6 +108,7 @@ Com_SRCS += osdThread.c
|
||||
Com_SRCS += osdThreadExtra.c
|
||||
Com_SRCS += osdThreadHooks.c
|
||||
Com_SRCS += osdMutex.c
|
||||
Com_SRCS += osdSpin.c
|
||||
Com_SRCS += osdEvent.c
|
||||
Com_SRCS += osdTime.cpp
|
||||
Com_SRCS += osdProcess.c
|
||||
|
||||
31
src/libCom/osi/epicsSpin.h
Normal file
31
src/libCom/osi/epicsSpin.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*************************************************************************\
|
||||
* 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();
|
||||
epicsShareFunc void epicsSpinDestroy(epicsSpinId);
|
||||
|
||||
epicsShareFunc void epicsSpinLock(epicsSpinId);
|
||||
epicsShareFunc int epicsSpinTryLock(epicsSpinId);
|
||||
epicsShareFunc void epicsSpinUnlock(epicsSpinId);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* epicsSpinh */
|
||||
71
src/libCom/osi/os/default/osdSpin.c
Normal file
71
src/libCom/osi/os/default/osdSpin.c
Normal file
@@ -0,0 +1,71 @@
|
||||
/*************************************************************************\
|
||||
* 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 "errlog.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsSpin.h"
|
||||
|
||||
/*
|
||||
* Default: EPICS MUTEX IMPLEMENTATION
|
||||
*/
|
||||
|
||||
typedef struct epicsSpin {
|
||||
epicsMutexId lock;
|
||||
} epicsSpin;
|
||||
|
||||
epicsSpinId epicsSpinCreate() {
|
||||
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;
|
||||
}
|
||||
|
||||
void epicsSpinDestroy(epicsSpinId spin) {
|
||||
epicsMutexDestroy(spin->lock);
|
||||
free(spin);
|
||||
}
|
||||
|
||||
void epicsSpinLock(epicsSpinId spin) {
|
||||
epicsMutexLockStatus status;
|
||||
|
||||
status = epicsMutexLock(spin->lock);
|
||||
if (status != epicsMutexLockOK) {
|
||||
errlogPrintf("epicsSpin epicsMutexLock failed: error %s\n",
|
||||
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("epicsSpin epicsMutexTryLock failed: error epicsMutexLockError\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
void epicsSpinUnlock(epicsSpinId spin) {
|
||||
epicsMutexUnlock(spin->lock);
|
||||
}
|
||||
154
src/libCom/osi/os/posix/osdSpin.c
Normal file
154
src/libCom/osi/os/posix/osdSpin.c
Normal file
@@ -0,0 +1,154 @@
|
||||
/*************************************************************************\
|
||||
* 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>
|
||||
|
||||
#include "errlog.h"
|
||||
#include "epicsSpin.h"
|
||||
|
||||
#define checkStatus(status,message) \
|
||||
if ((status)) { \
|
||||
errlogPrintf("epicsSpin %s failed: error %s\n", \
|
||||
(message), strerror((status))); \
|
||||
}
|
||||
|
||||
#if defined(_POSIX_SPIN_LOCKS) && (_POSIX_SPIN_LOCKS > 1)
|
||||
|
||||
/*
|
||||
* POSIX SPIN LOCKS IMPLEMENTATION
|
||||
*/
|
||||
|
||||
typedef struct epicsSpin {
|
||||
pthread_spinlock_t lock;
|
||||
} epicsSpin;
|
||||
|
||||
epicsSpinId epicsSpinCreate() {
|
||||
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");
|
||||
}
|
||||
|
||||
int epicsSpinTryLock(epicsSpinId spin) {
|
||||
int status;
|
||||
|
||||
status = pthread_spin_trylock(&spin->lock);
|
||||
if (status == EBUSY)
|
||||
return 1;
|
||||
checkStatus(status, "pthread_spin_trylock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void epicsSpinUnlock(epicsSpinId spin) {
|
||||
int status;
|
||||
|
||||
status = pthread_spin_unlock(&spin->lock);
|
||||
checkStatus(status, "pthread_spin_unlock");
|
||||
}
|
||||
|
||||
#else /* defined(_POSIX_SPIN_LOCKS) && (_POSIX_SPIN_LOCKS > 1) */
|
||||
|
||||
/*
|
||||
* POSIX MUTEX IMPLEMENTATION
|
||||
*/
|
||||
|
||||
typedef struct epicsSpin {
|
||||
pthread_mutex_t lock;
|
||||
} epicsSpin;
|
||||
|
||||
epicsSpinId epicsSpinCreate() {
|
||||
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");
|
||||
}
|
||||
|
||||
int epicsSpinTryLock(epicsSpinId spin) {
|
||||
int status;
|
||||
|
||||
status = pthread_mutex_trylock(&spin->lock);
|
||||
if (status == EBUSY)
|
||||
return 1;
|
||||
checkStatus(status, "pthread_mutex_trylock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void epicsSpinUnlock(epicsSpinId spin) {
|
||||
int status;
|
||||
|
||||
status = pthread_mutex_unlock(&spin->lock);
|
||||
checkStatus(status, "pthread_mutex_unlock");
|
||||
}
|
||||
|
||||
#endif /* defined(_POSIX_SPIN_LOCKS) && (_POSIX_SPIN_LOCKS > 1) */
|
||||
52
src/libCom/osi/os/vxWorks/osdSpin.c
Normal file
52
src/libCom/osi/os/vxWorks/osdSpin.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/*************************************************************************\
|
||||
* 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>
|
||||
*
|
||||
* based on epicsInterrupt.c (vxWorks implementation) by Marty Kraimer
|
||||
*/
|
||||
|
||||
/*
|
||||
* vxWorks (single CPU): LOCK INTERRUPT
|
||||
*
|
||||
* CAVEAT:
|
||||
* This implementation will break on vxWorks SMP architectures.
|
||||
* These architectures provide spinlocks, which will have to be used.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <intLib.h>
|
||||
|
||||
#include "epicsSpin.h"
|
||||
|
||||
typedef struct epicsSpin {
|
||||
int key;
|
||||
} epicsSpin;
|
||||
|
||||
epicsSpinId epicsSpinCreate() {
|
||||
return calloc(1, sizeof(*spin));
|
||||
}
|
||||
|
||||
void epicsSpinDestroy(epicsSpinId spin) {
|
||||
free(spin);
|
||||
}
|
||||
|
||||
void epicsSpinLock(epicsSpinId spin) {
|
||||
spin->key = intLock();
|
||||
}
|
||||
|
||||
int epicsSpinTryLock(epicsSpinId spin) {
|
||||
epicsSpinLock(spin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void epicsSpinUnlock(epicsSpinId spin) {
|
||||
intUnlock(spin->key);
|
||||
}
|
||||
Reference in New Issue
Block a user