What are you waiting for?
One of the common problems I’ve helped customers with is optimising their device startup time.
There are many things you can do to squeeze a few precious seconds out of your startup sequence, but one of the simplest may not be immediately obvious.
The sequence
devb-eide
waitfor /dev/hd0 30
…
is an all too common one, but it’s surprisingly damaging if you are trying to not waste cycles.
For one thing, it means that you can’t really start anything after the waitfor until devb-eide has gone through its sometimes lengthy initialization sequence (sorry devb, don’t mean to pick on you…).
Really all the system can do is to finish off the initialization of any servers you already started and poll for the device to appear.
Wait a second - POLL??!!!
Hmmm, in RTOS speak, Poll=BAD, WaitForAnEvent=GOOD!
Yes, my friends, it’s sad to say that /bin/waitfor (actually the amazingly versatile /bin/on) does actually poll, with a period of 100ms to boot, as does the builtin version that procnto provides when running your image’s startup script.
There are a number of nasties associated with this, one of the most annoying being that if your device appears 1ms after that 100ms poll (which is just a stat()) then you’re going to wait around for ANOTHER 99ms before waitfor notices!
And unless you have plenty else going on in the meantime then that means the dreaded idle thread will happily be using up your precious cpu. Another good reason to have plenty of servers started BEFORE you do the waitfor.
So how about a remedy?
Well, the basic version of waitfor looks something like this…
while we haven’t reached the max limit
do
stat the device
if it’s there, break out
delay 100ms
done
Wouldn’t it be nice if we could do something more like
while we haven’t reached the max limit
do
sleep for the remaining timeout, but wakeup if the device appears?
done
Well, as it happens, if you are running QNX6.3.0 SP2 or later, then there is actually a facility you can use. It’s a new flag to procmgr_event_notify, PROCMGR_EVENT_NAMESPACE,which will see a sigevent winging it’s way to you whenever the pathspace changes, which is basically whenever someone attaches or detaches a pathname.
So here’s a revised version of waitfor that waits until something changes, then hopefully stats the device.
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/procmgr.h>
#include <sys/siginfo.h>int main( int argc, char *argv[] )
{
struct sigevent event;
struct stat sbuf;
int timeout;
int total;
char *path;
time_t start, now;path = argv[1];
timeout = atoi(argv[2]);if ( stat( argv[1], &sbuf ) == 0 ) {
printf(”Found %s!\n”, path );
return EXIT_SUCCESS;
}SIGEV_UNBLOCK_INIT( &event );
procmgr_event_notify( PROCMGR_EVENT_PATHSPACE, &event );start = time(NULL);
do {
sleep( timeout );
if ( stat( argv[1], &sbuf ) == 0 ) {
printf(”Found %s!\n”, path );
return EXIT_SUCCESS;
}
now = time(NULL);
timeout -= (now - start);
start = now;
} while( timeout > 0 );
return EXIT_FAILURE;
}
If 99ms of idle time upsets you, this might help you sleep better.
Colin
PS - yes, this will be fixed in the next release of the kernel/utils, if I have anything to do with it.
PPS - I should mention that there is yet another location that waitfor is defined, that is the ewaitfor builtin in /bin/fesh. This version at least lets you set the poll period, as a third argument to ewaitfor. Again, that should be in 6.3.0 SP2 or later.
Comments(12)