rsrcdbmgr_attach()

Updated: April 19, 2023

Reserve a system resource for a process

Synopsis:

#include <sys/rsrcdbmgr.h>
#include <sys/rsrcdbmsg.h>

int rsrcdbmgr_attach( rsrc_request_t * list,
                      int count );

Arguments:

list
An array of rsrc_request_t structures that describe the resources that you want to reserve; see below.
count
The number of entries in the array.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The resource database manager allocates and keeps track of system resources. The system resources currently tracked are:

You can also track and access arbitrarily defined resources by using a string name as an identifier.

Major and minor device numbers are handled with separate rsrcdbmgr_devno_attach() and rsrcdbmgr_devno_detach() functions.

There are two main functions that drivers can use to communicate with the resource database:

The rsrcdbmgr_attach() function reserves a resource range(s) from the database of available resources for a process. Other processes can't reserve this resource range until the resource is returned to the system (usually with the rsrcdbmgr_detach() call). The requested resources are returned in a list of rsrc_request_t structures with the start and end fields filled in. The number of resources requested is specified in count.

Note:
  • In order to successfully use the rsrcdbmgr_*() functions to modify the resource database, your process must have the PROCMGR_AID_RSRCDBMGR ability enabled. For more information, see procmgr_ability().
  • Reserving the resources doesn't give you access to them; you still have to use mmap(), InterruptAttach(), or another means.

When you're finished with the resource, you must return it to the system. The easiest way to return the resource is to call rsrcdbmgr_detach() with the same start, end, and type (via the flags field) that were issued for the resource.

rsrc_request_t structure

The resource requests structure looks like this:

typedef struct _rsrc_request {
    uint64_t    length;
    uint64_t    align;
    uint64_t    start;
    uint64_t    end;
    uint32_t    flags;
    uint32_t    zero[2];
    const char *name;
} rsrc_request_t;

The members include:

length
The length of the resource that you want to reserve. You must set this member.
align
The alignment of the resource.
start, end
The range of resource that you want to reserve.
flags
The type of the resource, as well as flags that affect the request. You must either set this member to be one of the following resource types (defined in <sys/rsrcdbmgr.h>), or set it to RSRCDBMGR_FLAG_NAME and fill in the name field:
  • RSRCDBMGR_DMA_CHANNEL — DMA channel
  • RSRCDBMGR_IO_PORT — I/O port address
  • RSRCDBMGR_IRQ — Interrupt address
  • RSRCDBMGR_MEMORY — Memory address
  • RSRCDBMGR_PCI_MEMORY — PCI memory address

You can OR in the following flags (also defined in <sys/rsrcdbmgr.h>):

  • RSRCDBMGR_FLAG_ALIGN — the contents of the align field are valid, and the requested resource starts with the given alignment.
  • RSRCDBMGR_FLAG_LIST — this is one item in a list to search.
  • RSRCDBMGR_FLAG_NAME — the name field is valid, and is a system name.
  • RSRCDBMGR_FLAG_RANGE — the contents of the start and end fields are valid, and the requested resource is in the range start to end, inclusive.
  • RSRCDBMGR_FLAG_SHARE — other processes can have access to an allocated resource.
  • RSRCDBMGR_FLAG_TOPDOWN — start the search for a free resource block from end. If you also set RSRCDBMGR_FLAG_RANGE, this flag makes the search start from the end of the available range.
name
A pointer to the name of the resource class (NULL by default). This field is used only if you set RSRCDBMGR_FLAG_NAME in the flags field. The name must not start with a leading slash (/) and should be in the form:

type[/subtype[/subsubtype]].

The numeric constants map to the string-based resource names as follows:

Flag Name
RSRCDBMGR_MEMORY memory
RSRCDBMGR_IRQ irq
RSRCDBMGR_IO_PORT io
RSRCDBMGR_DMA_CHANNEL dma
RSRCDBMGR_PCI_MEMORY pcimemory

For example, normal I/O Ports (RSRCDBMGR_IO_PORT) are mapped to the string io. If you had a special class of io ports, you could access it with the name io/myspecialio. The subtype components are specific instances of the hierarchy, and as such, requests that are made higher up (e.g., a request for io) attempt to give out resources that aren't part of these specific instances.

Returns:

0 on success, or -1 if an error occurred (errno is set).

Errors:

EAGAIN
The resource request can't be filled.
EINTR
The call was interrupted by a signal.
EINVAL
Invalid argument.
ENOMEM
Insufficient memory to allocate internal data structures.
EPERM
The calling process doesn't have the required permission; see procmgr_ability().

Examples:

Note: When you start the system, the startup code and special programs that know how to probe the hardware call rsrcdbmgr_create() to register the hardware in the resource database. The following examples don't do this seeding, so they'll fail with an error code of EINVAL.

Example 1

/* 
 * Request one DMA Channel, with length 1, from the
 * entire range of available DMA channel resources.
 */
#include <stdio.h>
#include <sys/rsrcdbmgr.h>
#include <sys/rsrcdbmsg.h>

int main(int argc, char **argv) {
    int count;
    rsrc_request_t req;

    memset(&req, 0, sizeof(req));
    req.length = 1;
    req.flags = RSRCDBMGR_DMA_CHANNEL;
    count = 1;

    if (rsrcdbmgr_attach( &req, count) == -1) {
        perror("Problem attaching to resource ");
        exit(1);
    }

    printf("You can use DMA channel 0x%llx \n", 
            req.start);

    …
    /* Do something with the acquired resource */
    …

    /* To return the resource to the database: */
    if (rsrcdbmgr_detach( &req, count) == -1) {
        perror("Problem detaching resource \n");
        exit(1);
    }

    return(0);
}

Example 2

/* 
 * Request memory that's 4-byte aligned
 * and has a length of 50.
 */

#include <stdio.h>
#include <sys/rsrcdbmgr.h>
#include <sys/rsrcdbmsg.h>

int main(int argc, char **argv) {
    int count;
    rsrc_request_t req;

    memset(&req, 0, sizeof(req));
    req.align = 4;
    req.length = 50;
    req.flags = RSRCDBMGR_FLAG_ALIGN | RSRCDBMGR_MEMORY;
    count = 1;

    if (rsrcdbmgr_attach(&req, count) == -1) {
        perror("Problem attaching to resource ");
        exit(1);
    }

    printf("You can use memory from 0x%llx 0x%llx inclusive. \n", 
            req.start, req.end );

    …
    /* Do something with the acquired resource */
    …

    /* To return the resource to the database: */
    if (rsrcdbmgr_detach( &req, count) == -1) {
        perror("Problem detaching resource \n");
        exit(1);
    }

    return(0);
}

Example 3

/* 
 * Request two resources:
 * I/O port 0 and an IRQ in the range 10-12
 * from the available resources.
 */
#include <stdio.h>
#include <sys/rsrcdbmgr.h>
#include <sys/rsrcdbmsg.h>

int main(int argc, char **argv) {
    int count;
    rsrc_request_t req[2];

    memset(req, 0, 2*sizeof(*req));
    req[0].start = 0;
    req[0].end = 0;
    req[0].length = 1; 
    req[0].flags = RSRCDBMGR_FLAG_RANGE | RSRCDBMGR_IO_PORT;

    req[1].start = 10;
    req[1].end = 12;
    req[1].length = 1; 
    req[1].flags = RSRCDBMGR_FLAG_RANGE | RSRCDBMGR_IRQ;
    count = 2;

    if (rsrcdbmgr_attach(req, count) == -1) {
        perror("Problem attaching to resource ");
        exit(1);
    }

    printf("You can use io-port 0x%llx \n",
            req[0].start);
    printf("You can use irq 0x%llx \n", 
            req[1].start);

    …
    /* Do something with the acquired resource */
    …

    /* To return the resource to the database: */
    if (rsrcdbmgr_detach(req, count) == -1) {
        perror("Problem detaching resource \n");
        exit(1);
    }

    return(0);
}

Example 4

This example uses names instead of the constants for the resource type:

rsrc_alloc_t   alloc;
rsrc_request_t ralloc;

//Create a new resource

memset(&alloc, 0, sizeof(alloc));
alloc.start = 0x20000000;
alloc.end = 0x27ffffff;
alloc.flags = RSRCDBMGR_FLAG_NAME;
alloc.name = "io/Port_S0";
printf("Allocing %p %p %p \n", &alloc, &alloc.name, alloc.name);

if (rsrcdbmgr_create (&alloc, 1) == -1) {
   perror("create() 1 failed \n");
   return 1;
}

// Attach to the new resource, any range with 32 length

memset( &ralloc, 0, sizeof(ralloc));
ralloc.start = ralloc.end = 0;
ralloc.length = 32;
ralloc.flags = RSRCDBMGR_FLAG_NAME;
ralloc.name = "io/Port_S0";

if (rsrcdbmgr_attach (&ralloc, 1) == -1) {
   perror("attach() 2 failed \n");;
   return 1;
}

// Do something with the resource 

Classification:

QNX Neutrino

Safety:  
Cancellation point Yes
Interrupt handler No
Signal handler Yes
Thread Yes