Expose callback queue status
This allows tools like iocStats to monitor the queue status of the callback queues. This fixes lp:1786540.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsAtomic.h"
|
||||
#include "epicsSpin.h"
|
||||
#include "dbDefs.h"
|
||||
#include "epicsRingBytes.h"
|
||||
@@ -38,6 +39,7 @@ typedef struct ringPvt {
|
||||
volatile int nextPut;
|
||||
volatile int nextGet;
|
||||
int size;
|
||||
int highWaterMark;
|
||||
volatile char buffer[1]; /* actually larger */
|
||||
}ringPvt;
|
||||
|
||||
@@ -47,6 +49,7 @@ epicsShareFunc epicsRingBytesId epicsShareAPI epicsRingBytesCreate(int size)
|
||||
if(!pring)
|
||||
return NULL;
|
||||
pring->size = size + SLOP;
|
||||
pring->highWaterMark = 0;
|
||||
pring->nextGet = 0;
|
||||
pring->nextPut = 0;
|
||||
pring->lock = 0;
|
||||
@@ -131,8 +134,13 @@ epicsShareFunc int epicsShareAPI epicsRingBytesPut(
|
||||
if (pring->lock) epicsSpinUnlock(pring->lock);
|
||||
return 0;
|
||||
}
|
||||
if (nbytes)
|
||||
if (nbytes) {
|
||||
memcpy ((void *)&pring->buffer[nextPut], value, nbytes);
|
||||
int curUsed = pring->size - SLOP - freeCount;
|
||||
if (curUsed > epicsAtomicGetIntT(&pring->highWaterMark)) {
|
||||
epicsAtomicSetIntT(&pring->highWaterMark, curUsed);
|
||||
}
|
||||
}
|
||||
nextPut += nbytes;
|
||||
}
|
||||
else {
|
||||
@@ -143,8 +151,13 @@ epicsShareFunc int epicsShareAPI epicsRingBytesPut(
|
||||
}
|
||||
topCount = size - nextPut;
|
||||
copyCount = (nbytes > topCount) ? topCount : nbytes;
|
||||
if (copyCount)
|
||||
if (copyCount) {
|
||||
memcpy ((void *)&pring->buffer[nextPut], value, copyCount);
|
||||
int curUsed = pring->size - SLOP - freeCount;
|
||||
if (curUsed > epicsAtomicGetIntT(&pring->highWaterMark)) {
|
||||
epicsAtomicSetIntT(&pring->highWaterMark, curUsed);
|
||||
}
|
||||
}
|
||||
nextPut += copyCount;
|
||||
if (nextPut == size) {
|
||||
int nLeft = nbytes - copyCount;
|
||||
@@ -224,3 +237,15 @@ epicsShareFunc int epicsShareAPI epicsRingBytesIsFull(epicsRingBytesId id)
|
||||
{
|
||||
return (epicsRingBytesFreeBytes(id) <= 0);
|
||||
}
|
||||
|
||||
epicsShareFunc int epicsShareAPI epicsRingBytesHighWaterMark(epicsRingBytesIdConst id)
|
||||
{
|
||||
ringPvt *pring = (ringPvt *)id;
|
||||
return epicsAtomicGetIntT(&pring->highWaterMark);
|
||||
}
|
||||
|
||||
epicsShareFunc void epicsShareAPI epicsRingBytesResetHighWaterMark(epicsRingBytesId id)
|
||||
{
|
||||
ringPvt *pring = (ringPvt *)id;
|
||||
epicsAtomicSetIntT(&pring->highWaterMark, epicsRingBytesUsedBytes(id));
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ extern "C" {
|
||||
#include "shareLib.h"
|
||||
|
||||
typedef void *epicsRingBytesId;
|
||||
typedef void const *epicsRingBytesIdConst;
|
||||
|
||||
epicsShareFunc epicsRingBytesId epicsShareAPI epicsRingBytesCreate(int nbytes);
|
||||
/* Same, but secured by a spinlock */
|
||||
@@ -39,6 +40,8 @@ epicsShareFunc int epicsShareAPI epicsRingBytesUsedBytes(epicsRingBytesId id);
|
||||
epicsShareFunc int epicsShareAPI epicsRingBytesSize(epicsRingBytesId id);
|
||||
epicsShareFunc int epicsShareAPI epicsRingBytesIsEmpty(epicsRingBytesId id);
|
||||
epicsShareFunc int epicsShareAPI epicsRingBytesIsFull(epicsRingBytesId id);
|
||||
epicsShareFunc int epicsShareAPI epicsRingBytesHighWaterMark(epicsRingBytesIdConst id);
|
||||
epicsShareFunc void epicsShareAPI epicsRingBytesResetHighWaterMark(epicsRingBytesId id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -90,3 +90,15 @@ epicsShareFunc int epicsShareAPI epicsRingPointerIsFull(epicsRingPointerId id)
|
||||
voidPointer *pvoidPointer = reinterpret_cast<voidPointer*>(id);
|
||||
return((pvoidPointer->isFull()) ? 1 : 0);
|
||||
}
|
||||
|
||||
epicsShareFunc int epicsShareAPI epicsRingPointerGetHighWaterMark(epicsRingPointerIdConst id)
|
||||
{
|
||||
voidPointer const *pvoidPointer = reinterpret_cast<voidPointer const*>(id);
|
||||
return(pvoidPointer->getHighWaterMark());
|
||||
}
|
||||
|
||||
epicsShareFunc void epicsShareAPI epicsRingPointerResetHighWaterMark(epicsRingPointerId id)
|
||||
{
|
||||
voidPointer *pvoidPointer = reinterpret_cast<voidPointer*>(id);
|
||||
pvoidPointer->resetHighWaterMark();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* epicsRingPointerLocked uses a spinlock.
|
||||
*/
|
||||
|
||||
#include "epicsAtomic.h"
|
||||
#include "epicsSpin.h"
|
||||
#include "shareLib.h"
|
||||
|
||||
@@ -40,18 +41,22 @@ public: /* Functions */
|
||||
int getSize() const;
|
||||
bool isEmpty() const;
|
||||
bool isFull() const;
|
||||
int getHighWaterMark() const;
|
||||
void resetHighWaterMark();
|
||||
|
||||
private: /* Prevent compiler-generated member functions */
|
||||
/* default constructor, copy constructor, assignment operator */
|
||||
epicsRingPointer();
|
||||
epicsRingPointer(const epicsRingPointer &);
|
||||
epicsRingPointer& operator=(const epicsRingPointer &);
|
||||
int getUsedNoLock() const;
|
||||
|
||||
private: /* Data */
|
||||
epicsSpinId lock;
|
||||
volatile int nextPush;
|
||||
volatile int nextPop;
|
||||
int size;
|
||||
int highWaterMark;
|
||||
T * volatile * buffer;
|
||||
};
|
||||
|
||||
@@ -59,6 +64,7 @@ extern "C" {
|
||||
#endif /*__cplusplus */
|
||||
|
||||
typedef void *epicsRingPointerId;
|
||||
typedef void const *epicsRingPointerIdConst;
|
||||
|
||||
epicsShareFunc epicsRingPointerId epicsShareAPI epicsRingPointerCreate(int size);
|
||||
/* Same, but secured by a spinlock */
|
||||
@@ -74,6 +80,8 @@ epicsShareFunc int epicsShareAPI epicsRingPointerGetUsed(epicsRingPointerId id)
|
||||
epicsShareFunc int epicsShareAPI epicsRingPointerGetSize(epicsRingPointerId id);
|
||||
epicsShareFunc int epicsShareAPI epicsRingPointerIsEmpty(epicsRingPointerId id);
|
||||
epicsShareFunc int epicsShareAPI epicsRingPointerIsFull(epicsRingPointerId id);
|
||||
epicsShareFunc int epicsShareAPI epicsRingPointerGetHighWaterMark(epicsRingPointerIdConst id);
|
||||
epicsShareFunc void epicsShareAPI epicsRingPointerResetHighWaterMark(epicsRingPointerId id);
|
||||
|
||||
/* This routine was incorrectly named in previous releases */
|
||||
#define epicsRingPointerSize epicsRingPointerGetSize
|
||||
@@ -95,7 +103,8 @@ epicsShareFunc int epicsShareAPI epicsRingPointerIsFull(epicsRingPointerId id);
|
||||
|
||||
template <class T>
|
||||
inline epicsRingPointer<T>::epicsRingPointer(int sz, bool locked) :
|
||||
lock(0), nextPush(0), nextPop(0), size(sz+1), buffer(new T* [sz+1])
|
||||
lock(0), nextPush(0), nextPop(0), size(sz+1), highWaterMark(0),
|
||||
buffer(new T* [sz+1])
|
||||
{
|
||||
if (locked)
|
||||
lock = epicsSpinCreate();
|
||||
@@ -121,6 +130,10 @@ inline bool epicsRingPointer<T>::push(T *p)
|
||||
}
|
||||
buffer[next] = p;
|
||||
nextPush = newNext;
|
||||
int used = getUsedNoLock();
|
||||
if (used > epicsAtomicGetIntT(&highWaterMark)) {
|
||||
epicsAtomicSetIntT(&highWaterMark, used);
|
||||
}
|
||||
if (lock) epicsSpinUnlock(lock);
|
||||
return(true);
|
||||
}
|
||||
@@ -161,12 +174,19 @@ inline int epicsRingPointer<T>::getFree() const
|
||||
return n;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline int epicsRingPointer<T>::getUsedNoLock() const
|
||||
{
|
||||
int n = nextPush - nextPop;
|
||||
if (n < 0) n += size;
|
||||
return n;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline int epicsRingPointer<T>::getUsed() const
|
||||
{
|
||||
if (lock) epicsSpinLock(lock);
|
||||
int n = nextPush - nextPop;
|
||||
if (n < 0) n += size;
|
||||
int n = getUsedNoLock();
|
||||
if (lock) epicsSpinUnlock(lock);
|
||||
return n;
|
||||
}
|
||||
@@ -196,6 +216,18 @@ inline bool epicsRingPointer<T>::isFull() const
|
||||
return((count == 0) || (count == size));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline int epicsRingPointer<T>::getHighWaterMark() const
|
||||
{
|
||||
return epicsAtomicGetIntT(&highWaterMark);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void epicsRingPointer<T>::resetHighWaterMark()
|
||||
{
|
||||
epicsAtomicSetIntT(&highWaterMark, getUsed());
|
||||
}
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* INCepicsRingPointerh */
|
||||
|
||||
Reference in New Issue
Block a user