Merged Ralph's spinlocks branch.
Added an RTEMS implementation which locks interrupts, and some Release Notes mentioning the new API.
This commit is contained in:
@@ -14,7 +14,7 @@ OS_CLASS = Linux
|
||||
|
||||
CODE_CPPFLAGS = -D_REENTRANT
|
||||
|
||||
POSIX_CPPFLAGS = -D_POSIX_C_SOURCE=199506L -D_POSIX_THREADS -D_XOPEN_SOURCE=500
|
||||
POSIX_CPPFLAGS = -D_POSIX_C_SOURCE=200112L -D_POSIX_THREADS -D_XOPEN_SOURCE=500
|
||||
POSIX_LDLIBS = -lpthread
|
||||
|
||||
# -D_BSD_SOURCE for gethostname() in unistd.h as needed by cacChannelIO.cpp.
|
||||
|
||||
@@ -20,7 +20,7 @@ COMPILER_LDFLAGS += -mt
|
||||
|
||||
SOLARIS_VERSION = $(subst 5.,,$(shell uname -r))
|
||||
|
||||
POSIX_CPPFLAGS += -D_POSIX_C_SOURCE=199506L $(POSIX_CPPFLAGS_$(SOLARIS_VERSION))
|
||||
POSIX_CPPFLAGS += -D_POSIX_C_SOURCE=200112L $(POSIX_CPPFLAGS_$(SOLARIS_VERSION))
|
||||
POSIX_CPPFLAGS += -D_XOPEN_SOURCE=500
|
||||
POSIX_LDLIBS += -lposix4 -lpthread $(POSIX_LDLIBS_$(SOLARIS_VERSION))
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ COMPILER_LDFLAGS += -mt
|
||||
|
||||
SOLARIS_VERSION = $(subst 5.,,$(shell uname -r))
|
||||
|
||||
POSIX_CPPFLAGS += -D_POSIX_C_SOURCE=199506L $(POSIX_CPPFLAGS_$(SOLARIS_VERSION))
|
||||
POSIX_CPPFLAGS += -D_POSIX_C_SOURCE=200112L $(POSIX_CPPFLAGS_$(SOLARIS_VERSION))
|
||||
POSIX_CPPFLAGS += -D_XOPEN_SOURCE=500
|
||||
POSIX_LDLIBS += -lposix4 -lpthread $(POSIX_LDLIBS_$(SOLARIS_VERSION))
|
||||
|
||||
|
||||
@@ -15,6 +15,18 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.</p>
|
||||
<h2 align="center">Changes between 3.15.0.1 and 3.15.0.2</h2>
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
<h3>Spin-locks API added</h3>
|
||||
|
||||
<p>The new header file epicsSpin.h adds a portable spin-locks API which is
|
||||
intended for locking very short sections of code (typically one or two lines of
|
||||
C or C++) to provide a critical section that protects against race conditions.
|
||||
On Posix platforms this uses the pthread_spinlock_t type if it's available but
|
||||
falls back to a pthread_mutex_t if not; on the UP VxWorks and RTEMS platforms
|
||||
the implementations lock out the CPU interrupts; the default implementation
|
||||
(used where no better implementation is available for the platform) uses an
|
||||
epicsMutex. Spin-locks may not be taken recursively, and the code inside the
|
||||
critical section should always be short and deterministic.</p>
|
||||
|
||||
<h3>Improvements to aToIPAddr()</h3>
|
||||
|
||||
<p>The libCom routine aToIPAddr() and the vxWorks implementation of the
|
||||
|
||||
@@ -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 */
|
||||
54
src/libCom/osi/os/RTEMS/osdSpin.c
Normal file
54
src/libCom/osi/os/RTEMS/osdSpin.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*************************************************************************\
|
||||
* 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.
|
||||
* 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>
|
||||
*
|
||||
* Based on epicsInterrupt.c (RTEMS implementation) by Eric Norum
|
||||
*/
|
||||
|
||||
/*
|
||||
* RTEMS (single CPU): LOCK INTERRUPT
|
||||
*
|
||||
* CAVEAT:
|
||||
* This implementation is for UP architectures only.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <rtems.h>
|
||||
|
||||
#include "epicsSpin.h"
|
||||
|
||||
typedef struct epicsSpin {
|
||||
rtems_interrupt_level level;
|
||||
} epicsSpin;
|
||||
|
||||
epicsSpinId epicsSpinCreate() {
|
||||
return calloc(1, sizeof(epicsSpin));
|
||||
}
|
||||
|
||||
void epicsSpinDestroy(epicsSpinId spin) {
|
||||
free(spin);
|
||||
}
|
||||
|
||||
void epicsSpinLock(epicsSpinId spin) {
|
||||
rtems_interrupt_disable(spin->level);
|
||||
}
|
||||
|
||||
int epicsSpinTryLock(epicsSpinId spin) {
|
||||
epicsSpinLock(spin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void epicsSpinUnlock(epicsSpinId spin) {
|
||||
rtems_interrupt_enable(spin->level);
|
||||
}
|
||||
74
src/libCom/osi/os/default/osdSpin.c
Normal file
74
src/libCom/osi/os/default/osdSpin.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*************************************************************************\
|
||||
* 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 "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 not compile on vxWorks SMP architectures.
|
||||
* These architectures provide spinlocks, which must be used instead.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <intLib.h>
|
||||
|
||||
#include "epicsSpin.h"
|
||||
|
||||
typedef struct epicsSpin {
|
||||
int key;
|
||||
} epicsSpin;
|
||||
|
||||
epicsSpinId epicsSpinCreate() {
|
||||
return calloc(1, sizeof(epicsSpin));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -131,6 +131,11 @@ epicsMutexTest_SRCS += epicsMutexTest.cpp
|
||||
testHarness_SRCS += epicsMutexTest.cpp
|
||||
TESTS += epicsMutexTest
|
||||
|
||||
TESTPROD_HOST += epicsSpinTest
|
||||
epicsSpinTest_SRCS += epicsSpinTest.c
|
||||
testHarness_SRCS += epicsSpinTest.c
|
||||
TESTS += epicsSpinTest
|
||||
|
||||
TESTPROD_HOST += epicsAtomicTest
|
||||
epicsAtomicTest_SRCS += epicsAtomicTest.cpp
|
||||
testHarness_SRCS += epicsAtomicTest.cpp
|
||||
|
||||
185
src/libCom/test/epicsSpinTest.c
Normal file
185
src/libCom/test/epicsSpinTest.c
Normal file
@@ -0,0 +1,185 @@
|
||||
/*************************************************************************\
|
||||
* 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 epicsMutexTest by Marty Kraimer and Jeff Hill
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "epicsTime.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsSpin.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsUnitTest.h"
|
||||
#include "testMain.h"
|
||||
|
||||
typedef struct info {
|
||||
int threadnum;
|
||||
epicsSpinId spin;
|
||||
int quit;
|
||||
} info;
|
||||
|
||||
void spinThread(void *arg)
|
||||
{
|
||||
info *pinfo = (info *) arg;
|
||||
testDiag("spinThread %d starting", pinfo->threadnum);
|
||||
while (pinfo->quit--) {
|
||||
epicsSpinLock(pinfo->spin);
|
||||
testPass("spinThread %d epicsSpinLock taken", pinfo->threadnum);
|
||||
epicsThreadSleep(.1);
|
||||
epicsSpinUnlock(pinfo->spin);
|
||||
epicsThreadSleep(.9);
|
||||
}
|
||||
testDiag("spinThread %d exiting", pinfo->threadnum);
|
||||
return;
|
||||
}
|
||||
|
||||
static void lockPair(struct epicsSpin *spin)
|
||||
{
|
||||
epicsSpinLock(spin);
|
||||
epicsSpinUnlock(spin);
|
||||
}
|
||||
|
||||
static void tenLockPairs(struct epicsSpin *spin)
|
||||
{
|
||||
lockPair(spin);
|
||||
lockPair(spin);
|
||||
lockPair(spin);
|
||||
lockPair(spin);
|
||||
lockPair(spin);
|
||||
lockPair(spin);
|
||||
lockPair(spin);
|
||||
lockPair(spin);
|
||||
lockPair(spin);
|
||||
lockPair(spin);
|
||||
}
|
||||
|
||||
static void tenLockPairsSquared(struct epicsSpin *spin)
|
||||
{
|
||||
tenLockPairs(spin);
|
||||
tenLockPairs(spin);
|
||||
tenLockPairs(spin);
|
||||
tenLockPairs(spin);
|
||||
tenLockPairs(spin);
|
||||
tenLockPairs(spin);
|
||||
tenLockPairs(spin);
|
||||
tenLockPairs(spin);
|
||||
tenLockPairs(spin);
|
||||
tenLockPairs(spin);
|
||||
}
|
||||
|
||||
void epicsSpinPerformance ()
|
||||
{
|
||||
static const unsigned N = 10000;
|
||||
unsigned i;
|
||||
epicsSpinId spin;
|
||||
epicsTimeStamp begin;
|
||||
epicsTimeStamp end;
|
||||
double delay;
|
||||
|
||||
/* Initialize spinlock */
|
||||
spin = epicsSpinCreate();
|
||||
|
||||
/* test a single lock pair */
|
||||
epicsTimeGetCurrent(&begin);
|
||||
for ( i = 0; i < N; i++ ) {
|
||||
tenLockPairsSquared(spin);
|
||||
}
|
||||
epicsTimeGetCurrent(&end);
|
||||
|
||||
delay = epicsTimeDiffInSeconds(&end, &begin);
|
||||
delay /= N * 100u; /* convert to delay per lock pair */
|
||||
delay *= 1e6; /* convert to micro seconds */
|
||||
testDiag("lock()*1/unlock()*1 takes %f microseconds", delay);
|
||||
}
|
||||
|
||||
struct verifyTryLock {
|
||||
epicsSpinId spin;
|
||||
epicsEventId done;
|
||||
};
|
||||
|
||||
static void verifyTryLockThread(void *pArg)
|
||||
{
|
||||
struct verifyTryLock *pVerify =
|
||||
(struct verifyTryLock *) pArg;
|
||||
|
||||
testOk1(epicsSpinTryLock(pVerify->spin));
|
||||
epicsEventSignal(pVerify->done);
|
||||
}
|
||||
|
||||
static void verifyTryLock()
|
||||
{
|
||||
struct verifyTryLock verify;
|
||||
|
||||
verify.spin = epicsSpinCreate();
|
||||
verify.done = epicsEventMustCreate(epicsEventEmpty);
|
||||
|
||||
testOk1(epicsSpinTryLock(verify.spin) == 0);
|
||||
|
||||
epicsThreadCreate("verifyTryLockThread", 40,
|
||||
epicsThreadGetStackSize(epicsThreadStackSmall),
|
||||
verifyTryLockThread, &verify);
|
||||
|
||||
testOk1(epicsEventWait(verify.done) == epicsEventWaitOK);
|
||||
|
||||
epicsSpinUnlock(verify.spin);
|
||||
epicsSpinDestroy(verify.spin);
|
||||
epicsEventDestroy(verify.done);
|
||||
}
|
||||
|
||||
MAIN(epicsSpinTest)
|
||||
{
|
||||
const int nthreads = 3;
|
||||
const int nrounds = 5;
|
||||
unsigned int stackSize;
|
||||
epicsThreadId *id;
|
||||
int i;
|
||||
char **name;
|
||||
void **arg;
|
||||
info **pinfo;
|
||||
epicsSpinId spin;
|
||||
|
||||
testPlan(3 + nthreads * nrounds);
|
||||
|
||||
verifyTryLock();
|
||||
|
||||
spin = epicsSpinCreate();
|
||||
|
||||
id = (epicsThreadId *) calloc(nthreads, sizeof(epicsThreadId));
|
||||
name = (char **) calloc(nthreads, sizeof(char *));
|
||||
arg = (void **) calloc(nthreads, sizeof(void *));
|
||||
pinfo = (info **) calloc(nthreads, sizeof(info *));
|
||||
stackSize = epicsThreadGetStackSize(epicsThreadStackSmall);
|
||||
for (i = 0; i < nthreads; i++) {
|
||||
name[i] = (char *) calloc(10, sizeof(char));
|
||||
sprintf(name[i],"task%d",i);
|
||||
pinfo[i] = (info *) calloc(1, sizeof(info));
|
||||
pinfo[i]->threadnum = i;
|
||||
pinfo[i]->spin = spin;
|
||||
pinfo[i]->quit = nrounds;
|
||||
arg[i] = pinfo[i];
|
||||
id[i] = epicsThreadCreate(name[i], 40, stackSize,
|
||||
spinThread,
|
||||
arg[i]);
|
||||
}
|
||||
epicsThreadSleep(2.0 + nrounds);
|
||||
|
||||
epicsSpinPerformance();
|
||||
|
||||
return testDone();
|
||||
}
|
||||
Reference in New Issue
Block a user