The basic skeleton of a resource manager
QNX SDP8.0Getting Started with the QNX OSDeveloperUser
The following can be used as a template for a resource manager with multiple threads.
We've already seen a template that can be used for one with a single thread,
above in The resource manager library,
when we discussed a /dev/null resource manager.
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <string.h>
static resmgr_connect_funcs_t   connect_func;
static resmgr_io_funcs_t        io_func;
static iofunc_attr_t            attr;
int main (int argc, char **argv)
{
    thread_pool_attr_t    pool_attr;
    thread_pool_t         *tpp;
    dispatch_t            *dpp;
    resmgr_attr_t         resmgr_attr;
    int                   id;
    if ((dpp = dispatch_create ()) == NULL) {
        fprintf (stderr,
                 "%s:  Unable to allocate dispatch context.\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.handler_func  = (void *) dispatch_handler;
    pool_attr.context_free  = (void *) dispatch_context_free;
    // 1) set up the number of threads that you want
    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,
                                   POOL_FLAG_EXIT_SELF)) == NULL) {
        fprintf (stderr,
                 "%s:  Unable to initialize thread pool.\n",
                 argv [0]);
        return (EXIT_FAILURE);
    }
    iofunc_func_init (_RESMGR_CONNECT_NFUNCS, &connect_func,
                      _RESMGR_IO_NFUNCS, &io_func);
    iofunc_attr_init (&attr, S_IFNAM | 0777, 0, 0);
    // 2) override functions in "connect_func" and "io_func" as
    // required here
    memset (&resmgr_attr, 0, sizeof (resmgr_attr));
    resmgr_attr.nparts_max = 1;
    resmgr_attr.msg_max_size = 2048;
    // 3) replace "/dev/whatever" with your device name
    if ((id = resmgr_attach (dpp, &resmgr_attr, "/dev/whatever",
                _FTYPE_ANY, 0, &connect_func, &io_func, &attr)) == -1) {
        fprintf (stderr, "%s:  Unable to attach name.\n", argv [0]);
        return (EXIT_FAILURE);
    }
    // Never returns
    thread_pool_start (tpp);
    
    return (EXIT_SUCCESS);
}
For more information about the dispatch interface (i.e., the dispatch_create() function), see the documentation in the QNX OS C Library Reference.
- Step 1
 - Here you'd use the thread pool functions to create a pool of threads that will be able to service messages in your resource manager. Generally, I recommend that you start off with a single-threaded resource manager, as we did with the /dev/null example mentioned above. Once you have the basic functionality running, you can then add threads. You'd modify the lo_water, hi_water, increment, and maximum members of the pool_attr structure as described in the Threads & Processes chapter where we discuss the thread pool functions.
 - Step 2
 - Here you'd add whatever functions you want to supply. These are the outcalls we just
  discussed (e.g., read I/O function handler, device control I/O function handler.) For
  example, to add your own handler for the _IO_READ message that points to a
  function supplied by you called my_io_read(), you'd add the following
  line of code:
  
  
  
io_func.io_read = my_io_read;This overrides the POSIX-layer default function that got put into the table by iofunc_func_init() with a pointer to your function, my_io_read().
 - Step 3
 - You probably don't want your resource manager to be called /dev/whatever, so you should select an appropriate name. Note that the resmgr_attach() function is where you bind the attributes structure (the attr parameter) to the name—if you wish to have multiple devices handled by your resource manager, you'd call resmgr_attach() multiple times, with different attributes structures (so that you could tell the different registered names apart at runtime).
 
Page updated: 
