shm_ctl(), shm_ctl_special()

Give special attributes to a shared memory object

Synopsis:

#include <sys/mman.h>

int shm_ctl( int fd,
             int flags,
             uint64_t paddr,
             uint64_t size );

int shm_ctl_special( int fd,
                     int flags,
                     uint64_t paddr,
                     uint64_t size,
                     unsigned special );

Arguments:

fd
The file descriptor that's associated with the shared memory object, as returned by shm_open().
flags
A bitwise OR of one or more of the following bits, defined in <sys/mman.h>:
  • SHMCTL_ANON — allocate anonymous memory.
  • SHMCTL_GLOBAL — a hint that any mapping to the object could be global across all processes.
  • SHMCTL_HIGHUSAGE — a hint that the object is used a lot, and so the system should try to do things to speed up access to it.
  • SHMCTL_ISADMA — memory should be suitable for ISA DMA (e.g., it should be below 16 MB, and shouldn't cross 64 KB boundaries).
  • SHMCTL_LAZY — delay allocating the memory until it's referenced.

    If you create anonymous shared memory objects (by calling mmap() with MAP_ANON | MAP_SHARED and a file descriptor of -1), a MAP_LAZY flag implicitly sets the SHMCTL_LAZY flag on the object.

  • SHMCTL_LAZYWRITE — a hint that a mapping of this object could use lazy-writing mechanisms.
  • SHMCTL_LOWERPROT — a hint that the system may map this object in such a way that it trades lower memory protection for better performance.
  • SHMCTL_NODEFRAG — used with SHMCTL_PHYS | SHMCTL_ANON to specify that you want physically contiguous memory, but not so much that you're willing to wait for defragmentation. If contiguous memory isn't immediately available, the call gives an error of ENOMEM, and you can retry with just SHMCTL_ANON if you're willing to accept discontiguity.
  • SHMCTL_NOX64K — memory shouldn't cross 64 KB boundaries.
  • SHMCTL_PHYS — overlay the shared memory object onto the physical memory at paddr, or allocate physically contiguous memory if used with SHMCTL_ANON.
  • SHMCTL_PRIV — a hint that a mapping of this object may require privileged access.
  • SHMCTL_REPEAT — create a strided physical object; extend an existing object, initialized with the SHMCTL_PHYS flag, with a repeating pattern of physical addresses. For example:
    shm_ctl( fd, SHMCTL_PHYS, baseaddr, vstride );
    shm_ctl( fd, SHMCTL_REPEAT, pstride, count );
        
Note: Some of the bits have specific meanings for different processors. For more information, see:
paddr
The interpretation of this argument depends on the bits set in flags:
  • SHMCTL_PHYS — a physical address to assign to the object.
  • SHMCTL_REPEAT — the stride, which is used to increment the physical address given to the original shm_ctl() call

The value of this argument must be an even multiple of the page size (sysconf(_SC_PAGE_SIZE)).

size
The new size of the object, in bytes, regardless of the ANON/PHYS flag. If you specify SHMCTL_PHYS in the flags, then size must be an even multiple of the page size.

For SHMCTL_REPEAT, this argument is the length, which is used to increment the offset within the object. The value must be an even multiple of the page size.

special
(shm_ctl_special() only) Processor-specific flags; see the following:

Library:

libc

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

Description:

The shm_ctl() function modifies the attributes of the shared memory object identified by the handle, fd. This handle is the value returned by shm_open(). The shm_ctl_special() function is similar to shm_ctl(), but has an additional, processor-specific argument.

Your process might need some abilities enabled (see procmgr_ability()):

In order to use: You need:
SHMCTL_GLOBAL PROCMGR_AID_MEM_GLOBAL
SHMCTL_PHYS PROCMGR_AID_MEM_PHYS
shm_ctl_special() PROCMGR_AID_MEM_SPECIAL
Note:
  • The combination SHMCTL_ANON | SHMCTL_PHYS has the same behavior as for mmap(): it indicates that you want physically contiguous RAM to be allocated for the object.
  • On ARM targets, once you've called shm_ctl() for a shared memory object, you can't resize it. You must unmap and unlink the shared object, and then recreate it.
  • Calling shm_ctl_special() with a special argument of 0 isn't equivalent to calling shm_ctl(). There's an internal flag that tells the memory manager which function you called, so it can treat shared objects differently. Specifying 0 for special could clear some special bits that are on by default.

Bits in the flags argument for ARM processors

For ARMv7 processors:

Bits in the flags argument for x86 processors

For x86 processors:

Bits in the special argument for ARM processors

For ARM platforms, the special argument specifies the page table entry (PTE) bits to be set when the object is mapped.

Returns:

0
Success.
-1
An error occurred (errno is set).

Errors:

EAGAIN
(shm_ctl_special() only) The special value doesn't match the current special value.
EBADF
The shared memory object is already "special."
EINVAL
An invalid combination of flags was specified.
ENOMEM
One of the following:
  • There wasn't enough memory.
  • You specified SHMCTL_PHYS | SHMCTL_ANON | SHMCTL_NODEFRAG, and contiguous memory wasn't immediately available. You can retry with just SHMCTL_ANON if you're willing to accept discontiguity.
EPERM
The calling process doesn't have the required permission; see procmgr_ability().

Examples:

The following examples go together. Run sharephyscreator, followed by sharephysuser.

The sharephyscreator process maps in an area of physical memory and then overlays it with a shared memory object. The sharephysuser process opens that shared memory object in order to access the physical memory.

/*
 *  sharephyscreator.c
 *
 *  This maps in an area of physical memory and then
 *  overlays it with a shared memory object.  This way, another process
 *  can open that shared memory object in order to access the physical
 *  memory.  The other process in this case is sharephysuser.
 *
 *  Note that the size and address that you pass to shm_ctl() must be
 *  even multiples of the page size (sysconf(_SC_PAGE_SIZE)).
 *
 *  For VGA color text mode video memory:
 *    sharephyscreator /wally b8000
 *  Note that for VGA color text mode video memory, each character
 *  is followed by an attribute byte.  Here we just use a space.
*/

#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/neutrino.h>
#include <sys/stat.h>

char        *progname = "sharephyscreator";

main( int argc, char *argv[] )
{
    char        *text = "H e l l o   w o r l d ! ";
    int         fd, memsize;
    char        *ptr, *name;
    uint64_t    physaddr;
    
    if ( argc != 3 ) {
        printf( "Use: sharephyscreator shared_memory_object_name \
physical_address_in_hex\n" );
        printf( "Example: sharephyscreator wally b8000\n" );
        exit( EXIT_FAILURE );
    }
    name = argv[1];
    physaddr = atoh(argv[2]);
    memsize = sysconf( _SC_PAGE_SIZE ); /* this should be enough
                                           for our string */
   
    /* map in the physical memory */
    
    ptr = mmap_device_memory( 0, memsize, PROT_READ|PROT_WRITE, 0, physaddr );
    if ( ptr == MAP_FAILED ) {
        printf( "%s: mmap_device_memory for physical address %llx failed: %s\n",
            progname, physaddr, strerror(errno) );
        exit( EXIT_FAILURE );
    }

    /* open the shared memory object, create it if it doesn't exist */
    
    fd = shm_open( name, O_RDWR | O_CREAT, 0 );
    if ( fd == -1 ) {
        printf( "%s: error creating the shared memory object '%s': %s\n",
                progname, name, strerror(errno) );
        exit( EXIT_FAILURE );
    }
    
    /* overlay the shared memory object onto the physical memory */
    
    if ( shm_ctl( fd, SHMCTL_PHYS, physaddr, memsize ) == -1 ) {
        printf( "%s: shm_ctl failed: %s\n", progname, strerror(errno) );
        close( fd );
        munmap( ptr, memsize );
        shm_unlink( name );
        exit( EXIT_FAILURE );
    }
    strcpy( ptr, text ); /* write to the shared memory */
    
    printf( "\n%s: Physical memory mapped in, shared memory overlaid onto it.\n"
            "%s: Wrote '%s' to physical memory.\n"
            "%s: Sleeping for 20 seconds.  While this program is sleeping\n"
            "%s: run 'sharephysuser %s %d'.\n",
            progname, progname, ptr, progname, progname, name,
            strlen(text)+1 );
    sleep( 20 );
    
    printf( "%s: Woke up.  Cleaning up and exiting ...\n", progname );
    
    close( fd );
    munmap( ptr, memsize );
    shm_unlink( name );
}

The following is meant to be run with sharephyscreator.

/*
 *  sharephysuser.c
 *
 *  This one is meant to be run in tandem with sharephyscreator.
 *
 *  Run it as: sharephysuser shared_memory_object_name length
 *  Example: sharephysuser wally 49
 *
*/

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/neutrino.h>
#include <sys/stat.h>

char        *progname = "sharephysuser";

main( int argc, char *argv[] )
{
    int     fd, len, i;
    char    *ptr, *name;
    
    if ( argc != 3 ) {
        fprintf( stderr, "Use: sharephysuser shared_memory_object_name \
length\n" );
        fprintf( stderr, "Example: sharephysuser wally 49\n" );
        exit( EXIT_FAILURE );
    }
    name = argv[1];
    len = atoi( argv[2] );
    
    /* open the shared memory object */
    
    fd = shm_open( name, O_RDWR, 0 );
    if ( fd == -1 ) {
        fprintf( stderr, "%s: error opening the shared memory object '%s': %s\n",
                progname, name, strerror(errno) );
        exit( EXIT_FAILURE );
    }

    /* get a pointer to a piece of the shared memory, note that we
       only map in the amount we need to */
    
    ptr = mmap( 0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
    if ( ptr == MAP_FAILED ) {
        fprintf( stderr, "%s: mmap failed: %s\n", progname, strerror(errno) );
        exit( EXIT_FAILURE );
    }

    printf( "%s: reading the text: ", progname );
    for ( i = 0; i < len; i++ )
        printf( "%c", ptr[i] );
    printf( "\n" );

    close( fd );
    munmap( ptr, len );
}

Classification:

QNX Neutrino

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