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
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.
- Andrew
--
Complexity comes for free, Simplicity you have to work for.
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
Hi Mark,
You may need to call callbackSetPriority(PRIORITY, PCALLBACK) as well unless you allocate the epicsCallback structure using calloc(). The callback’s 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 doesn’t.
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.
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