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 SHMCTL_* flags, which are defined in
<sys/mman.h>.
- SHMCTL_ANON — allocate anonymous memory. If used with
SHMCTL_PHYS (i.e.,
SHMCTL_ANON | SHMCTL_PHYS), the memory allocated is physically contiguous; SHMCTL_ANON without SHMCTL_PHYS requests mostly contiguous memory. - SHMCTL_GET_FLAGS (QNX Neutrino 7.1 or later) — return the
flags defined for the object. If you specify this flag with other flags, the
existing flags, not the new ones in the call, are returned.
This flag is useful for learning if an object is assigned a physical address and hence, should not be given to unknown clients due to security risks, as explained in the paddr argument description below.
Note:The flags returned don't include SHMCTL_TYMEM because it applies only to the backing that's installed when you call a specific instance of shm_ctl(). The object might be backed in part by memory not from typed memory. - SHMCTL_GLOBAL (deprecated) — hint that any mapping to the object could be global across all processes.
- SHMCTL_HIGHUSAGE (deprecated) — hint that the object is used a lot, so the system should try to do things to speed up access to it.
- SHMCTL_LAZY — delay allocating the memory until it's referenced. This flag implies SHMCTL_ANON.
- SHMCTL_LOWERPROT (deprecated) — hint that the system may map this object in a way that trades lower memory protection for better performance.
- SHMCTL_PHYS — If used without SHMCTL_ANON or SHMCTL_TYMEM; overlay the shared memory object onto the physical memory at the address given in paddr.
- SHMCTL_PRIV (deprecated) — hint that a mapping of this object may require privileged access.
- SHMCTL_REPEAT — create a strided physical object; that is,
extend an existing object that was initialized with SHMCTL_PHYS,
with a repeating pattern of physical addresses. For example:
shm_ctl( fd, SHMCTL_PHYS, baseaddr, vstride ); shm_ctl( fd, SHMCTL_REPEAT, pstride, count ); - SHMCTL_REVOCABLE (QNX Neutrino 7.1 or later)
— allow the creator of the shared memory object to revoke access to it by
calling shm_revoke().
Only the creator of the object can set this flag; otherwise,
shm_ctl() fails and sets errno to
EPERM. After creating the object, you can either use this flag
alone or paired with another flag that you can toggle (e.g.
SHMCTL_SEAL).
For more information, see
Secure Buffer Management
in theShared Memory
chapter of the QNX Neutrino Programmer's Guide. -
SHMCTL_SEAL (QNX Neutrino 7.1 or later) — prevent the
object's layout (e.g., its size and backing memory) and attributes from being
modified. Only the process that created the object can set this flag; after it's
set, no process (including the object's creator) can modify the layout or change
any attributes. But, processes may still query the flags of an object with
SHMCTL_GET_FLAGS. Note:
- A sealed object is not write-protected. Anyone who has write access can still change the content of the object—they just can't shrink or extend it or otherwise make it point to memory not already referenced by it. The intent is to provide a safe way to use shared memory objects for interprocess communication.
- If you want to seal a shared memory object after calling shm_ctl() or shm_ctl_special() to configure the object, you must use shm_ctl(). Calling shm_ctl_special() specifying only SHMCTL_SEAL fails with an error of EBADF.
- SHMCTL_TYMEM (QNX Neutrino 7.1 or later) — allocate typed
memory from the pool identified by a file descriptor that was returned by a call
to posix_typed_mem_open(). It isn't necessary to keep
this file descriptor open after the call to shm_ctl().
If you specify SHMCTL_TYMEM, you must also specify SHMCTL_ANON. If and only if you specified the POSIX_TYPED_MEM_ALLOCATE_CONTIG flag for posix_typed_mem_open(), you must specify SHMCTL_PHYS in addition to SHMCTL_ANON and SHMCTL_TYMEM.
Note:Some of the bits have specific meanings for different processors. For more information, see: - SHMCTL_ANON — allocate anonymous memory. If used with
SHMCTL_PHYS (i.e.,
- paddr
- The interpretation of this argument depends on the bits set in flags:
- SHMCTL_PHYS, except when used with SHMCTL_TYMEM (see below) or with SHMCTL_ANON
— a physical address to assign to the object. When
SHMCTL_ANON | SHMCTL_PHYSis set, paddr should be 0, because any physical address pointed to by this argument will be ignored.DANGER:Sharing memory through the direct mapping of physical addresses is extremely dangerous, and you should avoid it.For example, suppose process A allocates some memory, maps it, determines the physical address, and gives the address to process B so that it can map the memory. Process B uses direct mapping. Process A can free the memory or terminate, and the memory could then be given to another process, while process B continues to use it. This could cause a process or even the kernel to crash later.
- SHMCTL_REPEAT — the stride, which is used to increment the physical address given to the original shm_ctl() call.
- SHMCTL_TYMEM — a file descriptor that was returned by a call to posix_typed_mem_open(), cast to be a uint64_t.
If paddr is a physical address or a stride, its value must be a multiple of the page size (
sysconf(_SC_PAGESIZE)). - SHMCTL_PHYS, except when used with SHMCTL_TYMEM (see below) or with SHMCTL_ANON
— a physical address to assign to the object. When
- size
- The new size of the object, in bytes, regardless of the ANON and PHYS flag settings.
If you specify SHMCTL_PHYS in the flags, then size must be
a 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 a multiple of the page size.
Note:You can call shm_ctl() multiple times and use the size argument to extend an existing object; for more information, seeExtending an existing object
below. - special
- (shm_ctl_special() only)
Processor-specific flags; see the following:
Note:Calling shm_ctl_special() with a special argument of 0 is not equivalent to calling shm_ctl(). Setting special to 0 can clear some special bits that are on by default.
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.
| 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 |
Typically, you can call shm_ctl() only once on a new object created with shm_open(). Reopening an existing object with the O_TRUNC flag doesn't make the object new again.
Shared memory objects that are populated with shm_ctl() are implicitly locked, unless you use the SHMCTL_LAZY flag.
Extending an existing object
- You can extend objects created with SHMCTL_PHYS (a physical address) in one of these ways:
- by seeking beyond the end of the object—typically with
lseek()—and
installing another physical address and size with
shm_ctl(... SHMCTL_PHYS ...) - by calling
shm_ctl(... SHMCTL_REPEAT ...)when the file descriptor is at the beginning of the object
- by seeking beyond the end of the object—typically with
lseek()—and
installing another physical address and size with
- Objects created with SHMCTL_ANON or SHMCTL_LAZY are extended to a new size that's the current offset plus the size provided in the shm_ctl() call. Note that you can't shrink an object; the second call is ignored if the resulting size is smaller than the current one. For the non-lazy case, memory is allocated to fill the difference between the previous and current sizes.
If you first initialized an object with shm_ctl_special(), all subsequent calls that follow the rules above must also be done with shm_ctl_special(), using the same special attributes.
Bits in the flags argument for x86 processors
For x86 processors:
- SHMCTL_LAZYWRITE causes Write Combining to be used.
Write Combining is normally used for write-only purposes, such as a video buffer, as a high-performance
alternative to PROT_NOCACHE:
- Writes are significantly faster than those to PROT_NOCACHE memory.
- Reads have the same performance as those from PROT_NOCACHE memory, so they could be slow.
- If memory has been previously mapped as a cached memory type, the caches must be flushed, or undefined behavior may result.
- Write Combining works on SMP systems.
Bits in the special argument for ARM processors
For ARM platforms, the special argument specifies the memory attributes that will be used when the object is mapped.
- Any non-RAM memory locations, that are mapped using mmap() with the PROT_NOCACHE protection type, are assigned device-nGnRnE as a default (ARM_SHMCTL_SO).
- Any RAM memory locations, that are mapped using mmap() with the PROT_NOCACHE protection type, are assigned Normal Uncached memory as a default (ARM_SHMCTL_NC).
- Cached memory locations mapped using mmap() are assigned Normal Write-back, Write-Allocate as a default (ARM_SHMCTL_WBWA).
Bits in the special argument for AArch64 processors,below.
- ARM_SHMCTL_SO
- Map the object with the Strongly Ordered memory attribute (device-nGnRnE).
This provides uncached access and provides implicit memory ordering
equivalent to a barrier before and after the memory access.
Non-RAM memory locations, that are mapped using mmap() with the PROT_NOCACHE protection type, are assigned as device-nGnRnE as a default.
All loads and stores must be aligned for the access size, otherwise a memory fault is triggered resulting in delivery of a SIGBUS signal.
- ARM_SHMCTL_DEV
- Map the object with the Device memory attribute (device-nGnRE).
This provides uncached access and is subject to the ordering rules
defined by the ARM Architecture Reference Manual.
Reads are performed using a single memory access with the size as specified by the load instruction.
Stores are performed using a single memory access with the size as specified by the load instruction.
An explicit memory barrier may be required after store operations to ensure visibility of the store to the memory system.
For an example on using this flag, see
Sharing device memory
below. - ARM_SHMCTL_NC
- Map the object with the Normal Uncached memory attribute.
This provides uncached access and is subject to the ordering rules
defined by the ARM Architecture Reference Manual.
Loads and stores may be performed to unaligned addresses, except for those instructions that always require correct alignment.
Stores can be merged into a write buffer before being written to the memory system.
An explicit memory barrier may be required after store operations to ensure visibility of the store to the memory system.
- ARM_SHMCTL_WT
- Map the object with the Normal Write-Through attribute.
This provides cacheable access, subject to the ordering rules for Normal memory types.
Loads and stores may be performed to unaligned addresses, except for those instructions that always require correct alignment.
Loads allocate a cache line and return data from the cache.
Stores don't cause allocation of a cache line. If a store hits in the cache, the cache is modified and the data is written to memory via a write buffer. If a store misses in the cache, the data is written to memory via a write buffer. Multiple stores may be merged in the write buffer before being written to the memory system.
- ARM_SHMCTL_WB
- Map the object with the Normal Write-Back attribute.
This provides cacheable access, subject to the ordering rules for Normal memory types.
Loads and stores may be performed to unaligned addresses, except for those instructions that always require correct alignment.
Loads allocate a cache line and return data from the cache.
Stores don't cause allocation of a cache line. If a store hits in the cache, the cache is modified and the line is marked for write back to the memory system at a later time. If a store misses in the cache, the data is written to memory via a write buffer. Multiple stores may be merged in the write buffer before being written to the memory system.
- ARM_SHMCTL_WBWA
- Map the object with the Normal Write-Back, Write-Allocate attribute.
This provides cacheable access, subject to the ordering rules for Normal memory types.
Loads and stores may be performed to unaligned addresses, except for those instructions that always require correct alignment.
Loads allocate a cache line and return data from the cache.
Stores allocate a cache line and modify the cache, marking the line for write back to the memory system at a later time.
- ARM_SHMCTL_SH
- Map the object with the Shareable memory attribute.
The memory may
be accessed by multiple observers (other processors or bus masters).
This is used to indicate that the memory has coherency requirements.
You'll almost always want to specify this flag.
For ARM_SHMCTL_NC, accesses are coherent with respect to loads and stores, and the additional coherency applies to load/store exclusive operations.
For ARM_SHMCTL_WT, ARM_SHMCTL_WB, and ARM_SHMCTL_WBWA, this indicates that hardware cache coherency is required.
The level at which this coherency applies is system dependent, and it may still require explicit cache maintenance to enforce coherency for memory accesses by other bus masters (e.g., DMA operations).
TEX remap facility,
which limits the range of memory attributes that can be used.
Versions of QNX Neutrino before 7.0 didn't use TEX remap, and this allowed
shm_ctl_special() to specify any attribute encoded via the TEX[2:0],
C, and B bits.
Any encoding using nonzero TEX[2:1] bits is no longer possible.
You can find full details of the ARM memory attributes and ordering requirements
in section A3.5, Memory types and attributes and the memory order model,
in the ARM Architecture Reference Manual (ARM DDI 0406).
Bits in the special argument for AArch64 processors
(QNX Neutrino 7.1 or later) For AArch64 platforms, the special argument specifies the memory and shareability attributes that will be used when the object is mapped.
You must specify one of the following memory attributes:
- AARCH64_PTE_DEV
- Map the object with the Device memory attribute (device-nGnRE).
This provides uncached access and is subject to the ordering rules
defined by the ARM Architecture Reference Manual.
All loads and stores must be aligned for the access size, otherwise a memory fault is triggered resulting in delivery of a SIGBUS signal.
Reads are performed using a single memory access with the size as specified by the load instruction.
Stores are performed using a single memory access with the size as specified by the load instruction.
An explicit memory barrier may be required after store operations to ensure visibility of the store to the memory system.
- AARCH64_PTE_NC
- Map the object with the Normal Uncached memory attribute.
This provides uncached access and is subject to the ordering rules
defined by the ARM Architecture Reference Manual.
Loads and stores may be performed to unaligned addresses, except for those instructions that always require correct alignment.
Stores can be merged into a write buffer before being written to the memory system.
An explicit memory barrier may be required after store operations to ensure visibility of the store to the memory system.
- AARCH64_PTE_SODEV
- Map the object with the Strongly Ordered memory attribute (device-nGnRnE).
This provides uncached access and provides implicit memory ordering
equivalent to a barrier before and after the memory access.
Non-RAM memory locations, that are mapped using mmap() with the PROT_NOCACHE protection type, are assigned as device-nGnRnE as a default.
All loads and stores must be aligned for the access size, otherwise a memory fault is triggered resulting in delivery of a SIGBUS signal.
- AARCH64_PTE_WBnWA
- Map the object with the Write-Back, No-Write-Allocate attribute.
- AARCH64_PTE_WBWA
- Map the object with the Normal Write-Back, Write-Allocate attribute.
This provides cacheable access, subject to the ordering rules for Normal memory types.
Loads and stores may be performed to unaligned addresses, except for those instructions that always require correct alignment.
Loads allocate a cache line and return data from the cache.
Stores allocate a cache line and modify the cache, marking the line for write back to the memory system at a later time.
- AARCH64_PTE_WTnWA
- Map the object with the Write-Through, No-Write-Allocate attribute.
You can use a bitwise OR to include one of the following shareability attributes:
- AARCH64_PTE_ISH
- Inner shareable.
- AARCH64_PTE_NSH
- Non-shareable (the default).
- AARCH64_PTE_OSH
- Outer shareable.
If you don't specify inner- or outer-shareable, the memory is non-shareable (AARCH64_PTE_NSH). This is almost never what you want for non-device memory (device memory is outer-shareable). Unless you have a reason not to, you should specify inner-shareable for non-device memory.
For more information, see the ARM Architecture Reference Manual.
Returns:
- 0
- Success.
- >0
- Success. If SHMCTL_GET_FLAGS is used, the function returns a bitfield of the flags that have been set by previous calls to shm_ctl() on the shared memory object.
- -1
- An error occurred (errno is set).
Errors:
- EAGAIN
- (shm_ctl_special() only) The special value doesn't match the current special value.
- EBADF
- One of the following occurred:
- The shared memory object is already
special.
- After calling shm_ctl() or shm_ctl_special() to configure a shared memory object, you tried to seal the object by calling shm_ctl_special() specifying only SHMCTL_SEAL
- The shared memory object is already
- EBUSY
- You tried to extend a contiguous anonymous object (created with
SHMCTL_ANON | SHMCTL_PHYS). - EINVAL
- Invalid arguments, including the following:
- An invalid combination of flags was specified.
- You specified SHMCTL_PHYS in the flags, but the value of paddr or size isn't a multiple of the page size.
- You tried to add segments inside an explicit physical object (created with SHMCTL_PHYS and a physical address).
- You specified SHMCTL_REPEAT in the flags, and the stride isn't a multiple of the page size.
- You specified SHMCTL_REVOCABLE in the flags, but the object wasn't populated with shm_ctl().
- ENOMEM
- There wasn't enough memory.
- EPERM
- One of the following occurred:
- The calling process doesn't have the required permission; see procmgr_ability().
- The creator specified SHMCTL_SEAL, so changes to the layout and flags are no longer permitted.
- You specified SHMCTL_REVOCABLE in the flags, but you're not the creator of the object.
Examples:
Sharing device memory
/*
* create_device_shm.c
*/
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <aarch64/mmu.h>
#include <stdint.h>
#include <assert.h>
#include <fcntl.h>
#define S1_SHM_NAME "shm_s1"
#define TOTAL_PAGE_SIZE (4096)
static char *src;
static int src_fd;
/** Remove the shared memory object and destroy the device memory */
void destroy_device_shm(int shm_fd, char *name)
{
close(shm_fd);
shm_unlink(name);
}
/**
* Create a shared memory object and configure it to simulate device memory.
* Return the file descriptor of the new object if successful, -1 otherwise.
*/
int create_device_shm(char *name, uint64_t size)
{
int fd;
int rc;
fd = shm_open(name, O_RDWR|O_CREAT|O_TRUNC, 0666);
if (fd < 0) {
return -1;
}
rc = shm_ctl_special(fd, SHMCTL_ANON | SHMCTL_PHYS, 0, size, ARM_SHMCTL_DEV);
if (rc != 0) {
destroy_device_shm(fd, name);
return -1;
}
return fd;
}
void cleanup()
{
munmap(src, TOTAL_PAGE_SIZE);
destroy_device_shm(src_fd, S1_SHM_NAME);
}
int main(void)
{
// Create device memory region
src_fd = create_device_shm(S1_SHM_NAME, TOTAL_PAGE_SIZE);
assert(src_fd >= 0);
// Map device memory into current address space
src = mmap(NULL, TOTAL_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, src_fd, 0);
assert(src != (void *)MAP_FAILED);
// Your code goes here
// Destroy device memory region
cleanup();
return 0;
}
Classification:
| Safety: | |
|---|---|
| Cancellation point | Yes |
| Interrupt handler | No |
| Signal handler | Yes |
| Thread | Yes |
