Sample code for handling interrupts

QNX SDP8.0Writing a Resource ManagerDeveloper
Here's an example of the relevant portions of the interrupt service thread and resource manager initialization:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <sys/neutrino.h>
#include <secpol/secpol.h>

#define INTNUM 0
static resmgr_connect_funcs_t   connect_funcs;
static resmgr_io_funcs_t        io_funcs;
static iofunc_attr_t            attr;
#define INT_PRIO_DEFAULT (30)

void *interrupt_thread(void *unused)
{
    struct sigevent event;
    int id;
    
    /* fill in "event" structure */
    SIGEV_INTR_INIT(&event);
    
    /* intNum is the desired interrupt level */
    id = InterruptAttachEvent(INTNUM, &event, 0);
    
    /*... insert your code here ... */
    while (1) {
        InterruptWait(0, NULL);
        /* do something about the interrupt, perhaps updating shared structures
        * in the resource manager; unmask the interrupt when done */
        InterruptUnmask(0, id);
    }
    
    return NULL;
}

int main(int argc, char **argv)
{
    dispatch_t            *dpp;
    dispatch_context_t    *ctp;
    int                   interrupt_prio = INT_PRIO_DEFAULT;
    int                   opt;
    pthread_attr_t        tattr;
    struct sched_param    sparam;

    /* look for a -i int_priority argument */
    while ((opt = getopt(argc, argv, "i:")) != -1) {
        switch (opt) {
        case 'i':
            interrupt_prio = atoi(optarg);
            break;
        default:
            fprintf(stderr, "Unknown options %c\n", opt);
            break;
        }
    }

    /* initialize dispatch interface */
    if ((dpp = dispatch_create_channel(-1,DISPATCH_FLAG_NOLOCK)) == NULL) {
        fprintf(stderr, "%s: Unable to allocate dispatch handle.\n", argv[0]);
        return EXIT_FAILURE;
    }

    iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs,
                     _RESMGR_IO_NFUNCS, &io_funcs);
    iofunc_attr_init(&attr, S_IFNAM | 0666, 0, 0);

    if (secpol_resmgr_attach(NULL, dpp, NULL, "/dev/sample", _FTYPE_ANY, 0,
                             &connect_funcs, &io_funcs, &attr, NULL) == -1) {
        fprintf(stderr, "%s: Unable to attach name.\n", argv[0]);
        return EXIT_FAILURE;
    }

    /* create a thread to handle interrupts */
    pthread_attr_init(&tattr);
    pthread_attr_setinheritsched(&tattr, PTHREAD_EXPLICIT_SCHED);
    pthread_attr_setschedpolicy(&tattr,  SCHED_FIFO);
    sparam.sched_priority = interrupt_prio;
    pthread_attr_setschedparam(&tattr, &sparam);
    
    if (pthread_create(NULL, &tattr, interrupt_thread, NULL) != EOK) {
        fprintf(stderr, "%s: Unable to create interrupt thread.\n", argv[0]);
        return EXIT_FAILURE;
    }

    ctp = dispatch_context_alloc(dpp);
    if (ctp == NULL) {
        perror("dispatch_context_alloc");
        exit(EXIT_FAILURE);
    }

    /* handle resource manager messages */
    while (1) {
        if (dispatch_block(ctp) == NULL) {
            fprintf(stderr, "dispatch_block failed: %s\n", strerror (errno));
            exit(EXIT_FAILURE);
        }
        (void)dispatch_handler(ctp);
    }
    
    return EXIT_SUCCESS;
}

Here the interrupt_thread() function uses InterruptAttachEvent() to bind the interrupt source (INTNUM) to the event (passed in event), and then waits for the event to occur.

This approach has a major advantage over using a pulse. A pulse is delivered as a message to the resource manager, which means that if the resource manager's message-handling threads are busy processing requests, the pulse will be queued until a thread does a MsgReceive().

With the InterruptWait() approach, if the thread that's executing the InterruptWait() is of sufficient priority, it unblocks and runs immediately after the SIGEV_INTR is generated.

The main() program accepts a command-line argument that configures the priority at which it will handle interrupts. This design allows you to configure the priority when you deploy the resource manager, not just when you write it.

Page updated: