/*
* raise the priority of the current thread hoping to improve our
* likelyhood of detecting a bug
*/ priorityOfTestThread = epicsThreadGetPrioritySelf (); epicsThreadSetPriority ( epicsThreadGetIdSelf(), epicsThreadPriorityHigh );
/*
* wait for the first subscription update to arrive
*/
{ epicsMutexLockStatus lockStatus = epicsMutexLock ( pTestData->m_mutex );
verify ( lockStatus == epicsMutexLockOK );
while ( pTestData->m_eventData[0].m_nCallback == 0 ) { epicsMutexUnlock ( pTestData->m_mutex ); epicsThreadSleep ( 50e-6 ); lockStatus = epicsMutexLock ( pTestData->m_mutex ); verify ( lockStatus == epicsMutexLockOK );
} epicsMutexUnlock ( pTestData->m_mutex );
}
/*
* try to destroy all of the subscriptions at precisely the same time that
* their first callbacks are running
*/
for ( j=0; j < multiSubscrDestroyNoLateCallbackEventCount; j++ ) {
SEVCHK ( ca_clear_event ( pTestData->m_eventData[j].m_id ) , NULL ); epicsMutexLockStatus lockStatus = epicsMutexLock ( pTestData->m_mutex );
verify ( lockStatus == epicsMutexLockOK ); pTestData->m_eventData[j].m_callbackIsOk = FALSE; epicsMutexUnlock ( pTestData->m_mutex );
}
/*
* return to the original priority
*/ epicsThreadSetPriority ( epicsThreadGetIdSelf(), priorityOfTestThread );
if ( i % 1000 == 0 ) { showProgress ( pTestData->m_interestLevel );
}
}
/*
* verify that, in a preemtive callback mode client, a subscription callback never
* comes after the subscription is destroyed
*/
static void multiSubscrDestroyNoLateCallbackTest ( const char *pName, unsigned interestLevel )
{
struct MultiSubscrDestroyNoLateCallbackTestData * pTestData;
I added this new regression test based on Michaels test
#define multiSubscrDest royNoLateCallba ckEventCount 500
struct MultiSubscrDest royNoLateCallba ckEventData { royNoLateCallba ckTestData * m_pTestData;
evid m_id;
size_t m_nCallback;
int m_callbackIsOk;
struct MultiSubscrDest
};
struct MultiSubscrDest royNoLateCallba ckTestData { royNoLateCallba ckEventData troyNoLateCallb ackEventCount] ;
const char * m_pChanName;
chid m_chan;
epicsMutexId m_mutex;
epicsEventId m_testDoneEvent;
unsigned m_interestLevel;
struct MultiSubscrDest
m_eventData [multiSubscrDes
};
static void noLateCallbackD etect ( struct event_handler_args args ) royNoLateCallba ckEventData * const pEventData = args.usr; ockStatus lockStatus = epicsMutexLock ( pEventData- >m_pTestData- >m_mutex ); >m_callbackIsOk ; >m_nCallback+ +; nlock ( pEventData- >m_pTestData- >m_mutex );
{
int callbackIsOk;
struct MultiSubscrDest
epicsMutexL
callbackIsOk = pEventData-
pEventData-
epicsMutexU
verify ( lockStatus == epicsMutexLockOK );
verify ( callbackIsOk );
}
static void multiSubscrDest royNoLateCallba ckThread ( void * pParm ) royNoLateCallba ckTestData * const pTestData = royNoLateCallba ckTestData * ) pParm;
{
struct MultiSubscrDest
( struct MultiSubscrDest
unsigned i, j;
int status;
status = ca_context_create ( ca_enable_ preemptive_ callback );
verify ( status == ECA_NORMAL );
status = ca_create_channel ( pTestData- >m_pChanName, 0, 0,
CA_ PRIORITY_ DEFAULT, &pTestData->m_chan ); troyLateNoCallb ackTest: channel connect failed" );
status = ca_pend_io ( timeoutToPendIO );
SEVCHK ( status, "multiSubscrDes
verify ( status == ECA_NORMAL );
/* hread; royNoLateCallba ckEventCount; j++ ) {
epicsMutex LockStatus lockStatus = epicsMutexLock ( pTestData->m_mutex );
pTestData- >m_eventData[ j].m_nCallback = 0;
pTestData- >m_eventData[ j].m_callbackIs Ok = TRUE;
pTestData- >m_eventData[ j].m_pTestData = pTestData;
epicsMutex Unlock ( pTestData->m_mutex ); etect,
&pTestData- >m_eventData[ j], &pTestData- >m_eventData[ j].m_id ) , NULL );
* create a set of subscriptions
*/
for ( i=0; i < 10000; i++ ) {
unsigned int priorityOfTestT
for ( j=0; j < multiSubscrDest
verify ( lockStatus == epicsMutexLockOK );
SEVCHK ( ca_add_event ( DBR_GR_FLOAT, pTestData->m_chan, noLateCallbackD
}
SEVCHK ( ca_flush_io(), NULL );
/*
priorityOfTest Thread = epicsThreadGetP rioritySelf ();
epicsThreadSet Priority ( epicsThreadGetI dSelf() , epicsThreadPrio rityHigh );
* raise the priority of the current thread hoping to improve our
* likelyhood of detecting a bug
*/
/*
epicsMutex LockStatus lockStatus = epicsMutexLock ( pTestData->m_mutex ); >m_eventData[ 0].m_nCallback == 0 ) {
epicsMutexUnl ock ( pTestData->m_mutex );
epicsThreadSl eep ( 50e-6 );
lockStatus = epicsMutexLock ( pTestData->m_mutex );
verify ( lockStatus == epicsMutexLockOK );
epicsMutex Unlock ( pTestData->m_mutex ); royNoLateCallba ckEventCount; j++ ) { >m_eventData[ j].m_id ) , NULL );
epicsMutex LockStatus lockStatus = epicsMutexLock ( pTestData->m_mutex );
pTestData- >m_eventData[ j].m_callbackIs Ok = FALSE;
epicsMutex Unlock ( pTestData->m_mutex );
epicsThreadSet Priority ( epicsThreadGetI dSelf() , priorityOfTestT hread );
* wait for the first subscription update to arrive
*/
{
verify ( lockStatus == epicsMutexLockOK );
while ( pTestData-
}
}
/*
* try to destroy all of the subscriptions at precisely the same time that
* their first callbacks are running
*/
for ( j=0; j < multiSubscrDest
SEVCHK ( ca_clear_event ( pTestData-
verify ( lockStatus == epicsMutexLockOK );
}
/*
* return to the original priority
*/
if ( i % 1000 == 0 ) {
showProgre ss ( pTestData- >m_interestLeve l );
}
}
SEVCHK ( ca_clear_channel ( pTestData->m_chan ), NULL );
ca_ context_ destroy ();
epicsEventM ustTrigger ( pTestData- >m_testDoneEven t );
}
/* royNoLateCallba ckTest ( const char *pName, unsigned interestLevel ) royNoLateCallba ckTestData * pTestData;
* verify that, in a preemtive callback mode client, a subscription callback never
* comes after the subscription is destroyed
*/
static void multiSubscrDest
{
struct MultiSubscrDest
showProgres sBegin ( "multiSubscrDes troyNoLateCallb ackTest" , interestLevel );
pTestData = calloc ( 1u, sizeof ( struct MultiSubscrDest royNoLateCallba ckTestData ) ); >m_mutex = epicsMutexMustC reate (); >m_testDoneEven t = epicsEventMustC reate ( epicsEventEmpty ); >m_pChanName = pName; >m_interestLeve l = interestLevel; MustCreate (
"multiSubscrDe stroyNoLateCall backTest" ,
epicsThreadPri orityLow,
epicsThreadGet StackSize ( epicsThreadStac kMedium ),
multiSubscrDes troyNoLateCallb ackThread,
pTestData );
verify ( pTestData );
pTestData-
pTestData-
pTestData-
pTestData-
epicsThread
/* ustWait ( pTestData- >m_testDoneEven t );
* wait for test to complete
*/
epicsEventM
/* estroy ( pTestData->m_mutex ); estroy ( pTestData- >m_testDoneEven t );
* cleanup
*/
epicsMutexD
epicsEventD
free ( pTestData );
showProgressEnd ( interestLevel );
}