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: