resmgr_connect_funcs_t connect table

Updated: April 19, 2023

When the resource manager library receives a message, it looks at the type of message and sees if it can do anything with it. In the base layer, there are two tables that affect this behavior: The resmgr_connect_funcs_t table, which contains a list of connect message handlers, and the resmgr_io_funcs_t table, which contains a similar list of I/O message handlers.

When it comes time to fill in the connect and I/O tables, we recommend that you use the iofunc_func_init() function to load up the tables with the POSIX-layer default handler routines. Then, if you need to override some of the functionality of particular message handlers, you'd simply assign your own handler function instead of the POSIX default routine. We'll see this in the section “Putting in your own functions.” Right now, let's look at the connect functions table itself (this is from <sys/resmgr.h>):

typedef struct _resmgr_connect_funcs {
  unsigned nfuncs;

  int (*open)
      (ctp, io_open_t *msg, handle, void *extra);
  int (*unlink)
      (ctp, io_unlink_t *msg, handle, void *reserved);
  int (*rename)
      (ctp, io_rename_t *msg, handle, io_rename_extra_t *extra);
  int (*mknod)
      (ctp, io_mknod_t *msg, handle, void *reserved);
  int (*readlink)
      (ctp, io_readlink_t *msg, handle, void *reserved);
  int (*link)
      (ctp, io_link_t *msg, handle, io_link_extra_t *extra);
  int (*unblock)
      (ctp, io_pulse_t *msg, handle, void *reserved);
  int (*mount)
      (ctp, io_mount_t *msg, handle, io_mount_extra_t *extra);

} resmgr_connect_funcs_t;

Note that I've shortened the prototype down by omitting the resmgr_context_t * type for the first member (the ctp), and the RESMGR_HANDLE_T * type for the third member (the handle). For example, the full prototype for open is really:

int (*open) (resmgr_context_t *ctp,
            io_open_t *msg,
            RESMGR_HANDLE_T *handle,
            void *extra);

The very first member of the structure (nfuncs) indicates how big the structure is (how many members it contains). In the above structure, it should contain the value “8,” for there are 8 members (open through to mount). This member is mainly in place to allow BlackBerry QNX to upgrade this library without any ill effects on your code. For example, suppose you had compiled in a value of 8, and then BlackBerry QNX upgraded the library to have 9. Because the member only had a value of 8, the library could say to itself, “Aha! The user of this library was compiled when we had only 8 functions, and now we have 9. I'll provide a useful default for the ninth function.” There's a manifest constant in <sys/resmgr.h> called _RESMGR_CONNECT_NFUNCS that has the current number. Use this constant if manually filling in the connect functions table (although it's best to use iofunc_func_init()).

Notice that the function prototypes all share a common format. The first parameter, ctp, is a pointer to a resmgr_context_t structure. This is an internal context block used by the resource manager library, and which you should treat as read-only (except for one field, which we'll come back to).

The second parameter is always a pointer to the message. Because the functions in the table are there to handle different types of messages, the prototypes match the kind of message that each function will handle.

The third parameter is a RESMGR_HANDLE_T structure called a handle—it's used to identify the device that this message was targeted at. We'll see this later as well, when we look at the attributes structure.

Note: In order to correctly define RESMGR_HANDLE_T, #include <sys/iofunc.h> before <sys/resmgr.h>.

Finally, the last parameter is either “reserved” or an “extra” parameter for functions that need some extra data. We'll show the extra parameter as appropriate during our discussions of the handler functions.