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 — 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_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 — 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 OS Programmer's Guide. -
SHMCTL_SEAL — 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 — 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.
- 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_PHYS
is set, paddr should be 0, because any physical address pointed to by this argument will be ignored.CAUTION: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/PHYS flag.
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.
- special
- (shm_ctl_special() only)
Processor-specific flags; see the following:
- Bits in the special argument for ARM processors
- Bits in the special argument for AArch64 processors
- Bits in the special argument for x86-64 processors
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.
- 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 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. 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.
Shared memory objects that are populated with shm_ctl() are implicitly locked.
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 OS 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
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.
Bits in the special argument for x86-64 processors
For x86-64 platforms, the special argument specifies the memory type that will be used when the object is mapped. The memory type dictates caching and ordering behaviors for memory accesses within the object.
The flags below are set on pages and defined in x86_64/mmu.h.
You must specify one of the following memory types:
- X86_64_PTE_MTYPE_WB
-
Map the object with the Write Back memory type.
Reads and writes of system memory are cached.
Writes are performed entirely in the cache when possible. Modified cache lines are written to system memory when a write-back operation is performed (e.g., cache lines need to be deallocated, cache maintenance).
Speculative reads are allowed.
Write combining is allowed.
- X86_64_PTE_MTYPE_WT
-
Map the object with the Write Through memory type.
All writes are written to a cache line when possible and through to system memory.
Reads and writes of system memory are cached.
Speculative reads are allowed.
Write combining is allowed.
This setting enforces coherency between caches in the processors and system memory.
- X86_64_PTE_MTYPE_WC
-
Map the object with the Write Combine memory type.
System memory locations are not cached.
Coherency is not enforced.
Speculative reads are allowed.
Writes may be delayed and combined to reduce memory accesses.
- X86_64_PTE_MTYPE_UC
-
Map the object with the Strong Uncacheable memory type.
Reads and writes are not cacheable.
Speculative reads are not permitted.
- X86_64_PTE_MTYPE_UCM
-
Map the object with the Uncacheable memory type.
This type setting has the same characteristics as Strong Uncacheable. The exception is that the UCM can be overriden by programming MTRRs for the WC memory type.
For more information, see the Intel Software Developers 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 |
Signal handler | Yes |
Thread | Yes |