|
Hi Andrew,
I reported in November 2025 issues with callbackRequestDelayed returning essentially immediately for delays less that 0.01 second.
I am happy to report that this works fine in base 7.0.10 on Linux and Windows.
This is the output on Linux:
epics> sleepTest1
epicsThreadSleepQuantum=0.010000
epicsThreadSleep: requested sleep time = 0.000010, actual=0.000084
epicsThreadSleep: requested sleep time = 0.000050, actual=0.000105
epicsThreadSleep: requested sleep time = 0.000100, actual=0.000152
epicsThreadSleep: requested sleep time = 0.000500, actual=0.000555
epicsThreadSleep: requested sleep time = 0.001000, actual=0.001055
epicsThreadSleep: requested sleep time = 0.002000, actual=0.002055
epicsThreadSleep: requested sleep time = 0.005000, actual=0.005055
epicsThreadSleep: requested sleep time = 0.010000, actual=0.010055
epicsThreadSleep: requested sleep time = 0.020000, actual=0.020057
callbackRequestDelayed: requested delay time = 0.000010, actual=0.000031
callbackRequestDelayed: requested delay time = 0.000050, actual=0.000118
callbackRequestDelayed: requested delay time = 0.000100, actual=0.000168
callbackRequestDelayed: requested delay time = 0.000500, actual=0.000531
callbackRequestDelayed: requested delay time = 0.001000, actual=0.001068
callbackRequestDelayed: requested delay time = 0.002000, actual=0.002068
callbackRequestDelayed: requested delay time = 0.005000, actual=0.005069
callbackRequestDelayed: requested delay time = 0.010000, actual=0.010070
callbackRequestDelayed: requested delay time = 0.020000, actual=0.020070
This is the output on Windows:
epics> sleepTest1
epicsThreadSleepQuantum=0.015625
epicsThreadSleep: requested sleep time = 0.000010, actual=0.000058
epicsThreadSleep: requested sleep time = 0.000050, actual=0.000543
epicsThreadSleep: requested sleep time = 0.000100, actual=0.000539
epicsThreadSleep: requested sleep time = 0.000500, actual=0.000959
epicsThreadSleep: requested sleep time = 0.001000, actual=0.001459
epicsThreadSleep: requested sleep time = 0.002000, actual=0.002478
epicsThreadSleep: requested sleep time = 0.005000, actual=0.005469
epicsThreadSleep: requested sleep time = 0.010000, actual=0.010385
epicsThreadSleep: requested sleep time = 0.020000, actual=0.020423
callbackRequestDelayed: requested delay time = 0.000010, actual=0.000039
callbackRequestDelayed: requested delay time = 0.000050, actual=0.000135
callbackRequestDelayed: requested delay time = 0.000100, actual=0.000646
callbackRequestDelayed: requested delay time = 0.000500, actual=0.001012
callbackRequestDelayed: requested delay time = 0.001000, actual=0.001668
callbackRequestDelayed: requested delay time = 0.002000, actual=0.002551
callbackRequestDelayed: requested delay time = 0.005000, actual=0.005533
callbackRequestDelayed: requested delay time = 0.010000, actual=0.010505
callbackRequestDelayed: requested delay time = 0.020000, actual=0.020168
The sscan record currently enforces a minimum delay of epicsThreadSleepQuantum, which does not make sense for Linux or Windows. I changed sscanTecord.c to remove that restriction except for vxWorks. I can now run the sscanRecord with delays below 1 ms, and
hence do fly scans faster than 1000 points/s.
I am making a PR for my new version.
Thanks,
Mark
From: Core-talk <core-talk-bounces at aps.anl.gov> on behalf of Mark Rivers via Core-talk <core-talk at aps.anl.gov>
Sent: Wednesday, November 12, 2025 3:11 PM
To: Johnson, Andrew N. <anj at anl.gov>
Cc: core-talk at aps.anl.gov <core-talk at aps.anl.gov>
Subject: RE: callbackRequestDelayed question
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.
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
|