EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  <20252026  Index 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  <20252026 
<== Date ==> <== Thread ==>

Subject: RE: callbackRequestDelayed question
From: Mark Rivers via Core-talk <core-talk at aps.anl.gov>
To: "Johnson, Andrew N." <anj at anl.gov>
Cc: "core-talk at aps.anl.gov" <core-talk at aps.anl.gov>
Date: Wed, 12 Nov 2025 21:11:29 +0000

Hi Andrew,

 

I moved my test routing inside an IOC and initialized the CALLBACK structure to 0 with ={0}.  The routine now runs fine, but I am getting a result I did not expect.  I have attached the new version of the code.

 

epics> sleepTest1

epicsThreadSleepQuantum=0.010000

epicsThreadSleep: requested sleep time = 0.000010, actual=0.000065

epicsThreadSleep: requested sleep time = 0.000050, actual=0.000103

epicsThreadSleep: requested sleep time = 0.000100, actual=0.000154

epicsThreadSleep: requested sleep time = 0.000500, actual=0.000553

epicsThreadSleep: requested sleep time = 0.001000, actual=0.001057

epicsThreadSleep: requested sleep time = 0.002000, actual=0.002055

epicsThreadSleep: requested sleep time = 0.005000, actual=0.005056

epicsThreadSleep: requested sleep time = 0.010000, actual=0.010035

epicsThreadSleep: requested sleep time = 0.020000, actual=0.020058

callbackRequestDelayed: requested delay time = 0.000010, actual=0.000027

callbackRequestDelayed: requested delay time = 0.000050, actual=0.000028

callbackRequestDelayed: requested delay time = 0.000100, actual=0.000021

callbackRequestDelayed: requested delay time = 0.000500, actual=0.000022

callbackRequestDelayed: requested delay time = 0.001000, actual=0.000024

callbackRequestDelayed: requested delay time = 0.002000, actual=0.000023

callbackRequestDelayed: requested delay time = 0.005000, actual=0.000021

callbackRequestDelayed: requested delay time = 0.010000, actual=0.005067

callbackRequestDelayed: requested delay time = 0.020000, actual=0.015070

 

Note that epicsThreadSleep sleeps for about 55 microseconds longer than requested, which may just be the overhead of epicsTimeGetCurrent after the sleep.

 

However, callbackRequestDelayed returns within about 25 microseconds for all delays less than 0.01 seconds, and returns .005 seconds too soon for .01 and .02 second delays.  This is disappointing, I was hoping it would have a behavior similar to epicsThreadSleep, so we can get accurate short delays.  Do you understand this?

 

Thanks,

Mark

 

 

From: Johnson, Andrew N. <anj at anl.gov>
Sent: Wednesday, November 12, 2025 11:37 AM
To: Mark Rivers <rivers at cars.uchicago.edu>
Subject: Re: callbackRequestDelayed question

 

Hi Mark,

 

Ahh, so this is outside of an IOC. Yes you will need to call callbackInit() first, there’s no lazy init code built into that as it’s normally only used within an IOC where initialization is handled for you. There might be other things you need to do as well if that doesn’t prove sufficient, the function iocBuild_1() in base/modules/database/src/ioc/misc/iocInit.c is where I would look for the other things the IOC sets up.

 

HTH,

 

- Andrew

 

-- 

Complexity comes for free, Simplicity you have to work for.

 

On 11/11/25, 6:23PM, "Mark Rivers" <rivers at cars.uchicago.edu> wrote:

 

This Message Is From an External Sender

This message came from outside your organization.

 

Hi Andrew,

 

Thanks for the quick response.

 

I added calls to callbackSetPriority and callbackSetUser, but it still crashes.

 

I have attached my test program.  It is designed to test the minimum usable times for epicsThreadSleep() and callbackRequestDelayed().

 

This is what I get when I run it with gdb.

 

Starting program: /home/epics/support/CARS/bin/linux-x86_64/sleepTest1

[Thread debugging using libthread_db enabled]

Using host libthread_db library "/lib64/libthread_db.so.1".

[New Thread 0x7ffff77ff640 (LWP 252197)]

[Thread 0x7ffff77ff640 (LWP 252197) exited]

epicsThreadSleepQuantum=0.010000

epicsThreadSleep: requested sleep time = 0.000010, actual=0.000067

epicsThreadSleep: requested sleep time = 0.000050, actual=0.000104

epicsThreadSleep: requested sleep time = 0.000100, actual=0.000153

epicsThreadSleep: requested sleep time = 0.000500, actual=0.000554

epicsThreadSleep: requested sleep time = 0.001000, actual=0.001054

epicsThreadSleep: requested sleep time = 0.002000, actual=0.002062

epicsThreadSleep: requested sleep time = 0.005000, actual=0.005059

epicsThreadSleep: requested sleep time = 0.010000, actual=0.010056

epicsThreadSleep: requested sleep time = 0.020000, actual=0.020056

[New Thread 0x7ffff7bfd640 (LWP 252198)]

[New Thread 0x7ffff77ff640 (LWP 252199)]

[New Thread 0x7ffff7afc640 (LWP 252200)]

[New Thread 0x7ffff6ffe640 (LWP 252201)]

[New Thread 0x7ffff6dfd640 (LWP 252202)]

 

Thread 1 "sleepTest1" received signal SIGSEGV, Segmentation fault.

0x00000000004b6f57 in epicsTimerStartDelay (pTmr=0x5b0000006e, delaySeconds=1.0000000000000001e-05) at ../timer/epicsTimer.cpp:258

258         pTmr->start ( *pTmr, delaySeconds );

Missing separate debuginfos, use: dnf debuginfo-install boost-system-1.75.0-10.el9.x86_64 glibc-2.34-168.el9_6.14.x86_64 libstdc++-11.5.0-5.el9_5.x86_64 ncurses-libs-6.2-10.20210508.el9.x86_64 readline-8.1-4.el9.x86_64

(gdb) bt

#0  0x00000000004b6f57 in epicsTimerStartDelay (pTmr=0x5b0000006e, delaySeconds=1.0000000000000001e-05) at ../timer/epicsTimer.cpp:258

#1  0x00000000004368ad in main (argc=<optimized out>, argv=<optimized out>) at ../sleepTest1.cpp:45

 

Note that I am calling callbackRequestDelayed() outside the context of an IOC.  Do I need to first call callbackInit()?

 

My motivation for this test is the sscan record.  It forces the values for the positioner delay and detector delay to be no smaller than epicsThreadSleepQuantum().  I believe this is a serious limitation on the performance of fly scans, and so I would like to investigate removing that restriction.  On Linux epicsThreadSleepQuantum is 10 ms, but I can get reliable epicsThreadSleep() for much shorter times.  I want to see if that is also true for callbackRequestDelayed(), since that is what the sscan record uses.

 

Thanks,

Mark

 

 

From: Johnson, Andrew N. <anj at anl.gov>
Sent: Tuesday, November 11, 2025 5:58 PM
To: Mark Rivers <rivers at cars.uchicago.edu>
Subject: Re: callbackRequestDelayed question

 

Hi Mark,

 

You may need to call callbackSetPriority(PRIORITY, PCALLBACK) as well unless you allocate the epicsCallback structure using calloc(). The callbacks priority is used as an index into an array and must be in the range 0-2. I could see that an uninitialized value there might cause a crash, so that might be your issue. Looking at the code in modules/database/src/ioc/db/callback.c it looks like it gets checked, but there might be some paths where it doesnt.

 

I can look further tomorrow if you don’t find an answer before then.

 

- Andrew

 

-- 

Complexity comes for free, Simplicity you have to work for.

 

On 11/11/25, 5:35PM, "Mark Rivers" <rivers at cars.uchicago.edu> wrote:

 

This Message Is From an External Sender

This message came from outside your organization.

 

Hi Andrew,

 

I am trying to use callbackRequestDelayed.  The calls I am making are:

 

  CALLBACK delayCallback;

  callbackSetCallback(myCallback, &delayCallback);

 callbackRequestDelayed(&delayCallback, requestedTime);

 

My program compiles with no warnings.  But it crashes at run-time with this:

 

#0  0x00000000004b6f47 in epicsTimerStartDelay (pTmr=0x5b0000006e, delaySeconds=1.0000000000000001e-05) at ../timer/epicsTimer.cpp:258

#1  0x00000000004368a5 in main (argc=<optimized out>, argv=<optimized out>) at ../sleepTest1.cpp:44

 

Is there something I need to do to initialize the timer for the delayed callback or something?

 

Thanks,

Mark

 

#include <epicsThread.h>
#include <epicsTime.h>
#include <callback.h>
#include <iocsh.h>
#include <epicsExport.h>
#include <stdio.h>

epicsTimeStamp start, end;
double requestedTime, actualTime;
bool callbackDone;

static void myCallback(CALLBACK *pCallBack) {
   actualTime = epicsTimeDiffInSeconds(&end, &start);
   epicsTimeGetCurrent(&end);
   actualTime = epicsTimeDiffInSeconds(&end, &start);
   printf("callbackRequestDelayed: requested delay time = %f, actual=%f\n", requestedTime, actualTime);
   callbackDone = true;
}

void sleepTest1(void)
{
  double sleepTimes[] = {10e-6, 50e-6, 100e-6, 500e-6, 1e-3, 2e-3, 5e-3, 10e-3, 20e-3};
  int numSleepTimes = sizeof(sleepTimes)/sizeof(sleepTimes[0]);
  double quantum = epicsThreadSleepQuantum();
  double actualTime;
  CALLBACK delayCallback={0};

  printf("epicsThreadSleepQuantum=%f\n", quantum);
   
  for (int i=0; i<numSleepTimes; i++) {
    epicsTimeGetCurrent(&start);
    requestedTime = sleepTimes[i];
    epicsThreadSleep(requestedTime);
    epicsTimeGetCurrent(&end);
    actualTime = epicsTimeDiffInSeconds(&end, &start);
    printf("epicsThreadSleep: requested sleep time = %f, actual=%f\n", requestedTime, actualTime);
  }

  callbackSetCallback(myCallback, &delayCallback);
  callbackSetPriority(priorityMedium, &delayCallback);
  callbackSetUser(&requestedTime, &delayCallback);
  for (int i=0; i<numSleepTimes; i++) {
    epicsTimeGetCurrent(&start);
    requestedTime = sleepTimes[i];
    callbackDone = false;
    callbackRequestDelayed(&delayCallback, requestedTime);
    while (!callbackDone) epicsThreadSleep(0.1);
  }

}

static const iocshFuncDef sleepTest1FuncDef = {"sleepTest1",0,0};
static void sleepTest1CallFunc(const iocshArgBuf* dummy)
{
    sleepTest1();
}

void sleepTest1Register(void)
{
    iocshRegister(&sleepTest1FuncDef,sleepTest1CallFunc);
}

epicsExportRegistrar(sleepTest1Register);


Replies:
Re: callbackRequestDelayed question Michael Davidsaver via Core-talk

Navigate by Date:
Prev: Build failed: epics-base base-arrayRecords-6 AppVeyor via Core-talk
Next: Re: callbackRequestDelayed question Michael Davidsaver via Core-talk
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  <20252026 
Navigate by Thread:
Prev: Build failed: epics-base base-arrayRecords-6 AppVeyor via Core-talk
Next: Re: callbackRequestDelayed question Michael Davidsaver via Core-talk
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  <20252026 
ANJ, 12 Nov 2025 · Home · News · About · Talk · Base · Modules · Extensions ·
· Distributions · Download · Documents · Links · Licensing ·