Locking memory

The QNX Neutrino RTOS supports POSIX memory locking, so that a process can avoid the latency of fetching a page of memory, by locking the memory so that the page is memory-resident (i.e., it remains in physical memory).

The levels of locking are as follows:

Unlocked
Unlocked memory can be paged in and out. Memory is allocated when it's mapped, but page table entries aren't created. The first attempt to access the memory fails, and the thread stays in the WAITPAGE state while the memory manager initializes the memory and creates the page table entries.

Failure to initialize the page results in the receipt of a SIGBUS signal.

Locked
Locked memory may not be paged in or out. Page faults can still occur on access or reference, to maintain usage and modification statistics. Pages that you think are PROT_WRITE are still actually PROT_READ. This is so that, on the first write, the kernel may be alerted that a MAP_PRIVATE page now is different from the shared backing store, and must be privatized.

To lock and unlock a portion of a thread's memory, call mlock() and munlock(); to lock and unlock all of a thread's memory, call mlockall() and munlockall(). The memory remains locked until the process unlocks it, exits, or calls an exec*() function. If the process calls fork(), a posix_spawn*() function, or a spawn*() function, the memory locks are released in the child process.

More than one process can lock the same (or overlapping) region; the memory remains locked until all the processes have unlocked it. Memory locks don't stack; if a process locks the same region more than once, unlocking it once undoes all of the process's locks on that region.

To lock all memory for all applications, specify the -ml option for procnto. Thus all pages are at least initialized (if still set only to PROT_READ).

Superlocked
(A QNX Neutrino extension) No faulting is allowed at all; all memory must be initialized and privatized, and the permissions set, as soon as the memory is mapped. Superlocking covers the thread's whole address space.

To superlock memory, obtain I/O privileges by:

  1. Enabling the PROCMGR_AID_IO ability for the process. For more information, see procmgr_ability().
  2. Calling ThreadCtl(), specifying the _NTO_TCTL_IO flag:
    ThreadCtl( _NTO_TCTL_IO, 0 );
        

To superlock all memory for all applications, specify the -mL option for procnto. Attaching an interrupt service routine (ISR) also superlocks a process's memory.

For MAP_LAZY mappings, memory isn't allocated or mapped until the memory is first referenced for any of the above types. Once it's been referenced, it obeys the above rules—it's a programmer error to touch a MAP_LAZY area in a critical region (where interrupts are disabled or in an ISR) that hasn't already been referenced.