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:
Ralph Lange
2012-10-29 20:25:23 +01:00
parent f9135c39cd
commit a977edfaa6
5 changed files with 310 additions and 0 deletions

View File

@@ -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

View 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 */

View 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);
}

View 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) */

View 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);
}