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>

#define INTNUM 0
static resmgr_connect_funcs_t   connect_funcs;
static resmgr_io_funcs_t        io_funcs;
static iofunc_attr_t            attr;

void interrupt_thread (void unused)
{
    struct sigevent event;
    int id;

    /* fill in "event" structure */
    memset(&event, 0, sizeof(event));
    event.sigev_notify = SIGEV_INTR_INIT(&event);

    /* intNum is the desired interrupt level */
    id = InterruptAttachEvent (INTNUM, &event, 0);

    /*... insert your code here ... */
    while (1) {
        InterruptWait (NULL, NULL);
        /*  do something about the interrupt,
         *  perhaps updating some shared structures in the resource manager
         *  unmask the interrupt when done */
        InterruptUnmask(0, id);
    }
}

int main(int argc, char **argv)
{
    thread_pool_attr_t    pool_attr;
    dispatch_t            *dpp;
    thread_pool_t         *tpp;
    int                   id;

    if((dpp = dispatch_create()) == NULL) {
        fprintf(stderr, "%s: Unable to allocate dispatch handle.\n", argv[0]);
        return EXIT_FAILURE;
    }

    memset(&pool_attr, 0, sizeof pool_attr);
    pool_attr.handle = dpp;
    pool_attr.context_alloc = (void *) dispatch_context_alloc;
    pool_attr.block_func = (void *) dispatch_block;
    pool_attr.unblock_func = (void *) dispatch_unblock;
    pool_attr.handler_func = (void *) dispatch_handler;
    pool_attr.context_free = (void *) dispatch_context_free;
    pool_attr.lo_water = 2;
    pool_attr.hi_water = 4;
    pool_attr.increment = 1;
    pool_attr.maximum = 50;

    if((tpp = thread_pool_create(&pool_attr,0)) == NULL) {
        fprintf(stderr, "%s: Unable to initialize thread pool.\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((id = 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;
    }

    thread_pool_start(tpp);

    /* handle interrupts */
    interrupt_thread();

    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.

Page updated: