You’ve been waiting long enough!

In my previous post on the problems with a polling waitfor, I mentioned that there was a timing window in which we could miss the notification event.

If the path we were looking for was attached in between the stat() and the procmgr_event_notify() call (admittedly a small window) then we would end up waiting the entire timeout duration before noticing that the path had appeared.

Here’s a new version that uses a pulse that closes that hole, by using a pulse as the notification event.

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/netmgr.h>
#include <sys/neutrino.h>

#include <sys/procmgr.h>
#include <sys/siginfo.h>

#define PULSE_CODE_TIMEOUT      _PULSE_CODE_MINAVAIL
#define PULSE_CODE_PATHSPACE    PULSE_CODE_TIMEOUT+1

int main( int argc, char *argv[] )
{
    struct itimerspec   timeout;
    int                 timer_id;
    struct sigevent     event;
    struct stat         sbuf;
    int                 chid, coid;
    char                *path;
    struct _pulse       pulse;

    path = argv[1];
    memset( &timeout, 0, sizeof(timeout) );
    timeout.it_value.tv_sec = atoi(argv[2]);

    chid = ChannelCreate(0);
    coid = ConnectAttach( ND_LOCAL_NODE, 0, chid, _NTO_SIDE_CHANNEL, 0 );

    SIGEV_PULSE_INIT( &event, coid, getprio(0), PULSE_CODE_TIMEOUT, 0 );
    timer_create( CLOCK_REALTIME, &event, &timer_id );

    /* make sure PATHSPACE event has higher priority */
    SIGEV_PULSE_INIT( &event, coid, getprio(0)+1, PULSE_CODE_PATHSPACE, 0 );
    procmgr_event_notify( PROCMGR_EVENT_PATHSPACE, &event );

    /* Check to make sure we don't wait for something already there... */
    if ( stat( argv[1], &sbuf ) == 0 ) {
        printf("Found %s\\n", path );
        return EXIT_SUCCESS;
    }

    timer_settime( timer_id, 0, &timeout, NULL );

    while( MsgReceivePulse( chid, &pulse, sizeof(pulse), NULL ) == 0 ) {
        switch(pulse.code) {
        case PULSE_CODE_PATHSPACE:
            if ( stat( argv[1], &sbuf ) == 0 ) {
                printf("Found %s\\n", path );
                return EXIT_SUCCESS;
            }
            break;
        case PULSE_CODE_TIMEOUT:
            printf("Timed out waiting for %s\\n", path);
            return EXIT_FAILURE;
        default:
            printf("Unknown pulse code %d waiting for %s\\n", pulse.code, path);
            return EXIT_FAILURE;
        }
    }
    return EXIT_FAILURE;
}

Note that I use a timeout pulse too, and make the timeout pulse have a lower priority than the notification pulse. This is because pulses queue in priority order, and I want to make sure that I receive the path event pulse first.

Cheers,

Colin

2 comments so far

  1. Mario on

    If you allow me to be picky ;-) Variable total is unused. Also I assume it’s a http glitch but I assume you meant \n and not !n in the printfs?

    Thanks a bunch! Always looking for way to speed startup ;-)

  2. colinburgess on

    Yes, total is out of there, and the \n was a real pain to add – what does wordpress not understand about preformatted tags???


Leave a comment