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: