Bound multiprocessing (BMP)
Bound multiprocessing provides the scheduling control of an asymmetric multiprocessing model, while preserving the hardware abstraction and management of symmetric multiprocessing.
BMP is similar to SMP, but you can specify which processors a thread can run on. You can use both SMP and BMP on the same system, allowing some threads to migrate from one processor to another, while other threads are restricted to one or more processors.
As with SMP, a single copy of the OS maintains an overall view of all system resources, allowing them to be dynamically allocated and shared among applications. But, during application initialization, a setting determined by the system designer forces all of an application's threads to execute only on a specified CPU.
Compared to full, floating SMP operation, this approach offers several advantages:
- It eliminates the cache thrashing that can reduce performance in an SMP system by allowing applications that share the same data set to run exclusively on the same CPU.
- It offers simpler application debugging than SMP since all execution threads within an application run on a single CPU.
- It helps legacy applications that use poor techniques for synchronizing shared data to run correctly, again by letting them run on a single CPU.
With BMP, an application locked to one CPU can't use other CPUs, even if they're idle. However, the QNX Neutrino RTOS lets you dynamically change the designated CPU, without having to checkpoint, and then stop and restart the application.
QNX Neutrino supports the concept of hard processor
affinity through a runmask.
Each bit that's set in the runmask represents a processor that a
thread can run on. By default, a thread's runmask
is set to all ones, allowing it to run on any processor. A
value of 0x01 would allow a thread to execute
only on the first processor.
By default, a process's or thread's children don't inherit the runmask; there's a separate inherit mask.
By careful use of these masks, a systems designer can further optimize the runtime performance of a system (e.g., by relegating nonrealtime processes to a specific processor). In general, however, this shouldn't be necessary, because our realtime scheduler will always preempt a lower-priority thread immediately when a higher-priority thread becomes ready. Processor locking will likely affect only the efficiency of the cache, since threads can be prevented from migrating.
You can specify the runmask for a new thread or process by:
- calling
posix_spawnattr_setrunmask(),
using
posix_spawnattr_setxflags()
to set the POSIX_SPAWN_EXPLICIT_CPU extended flag, and then calling
posix_spawn()
Or:
- setting the runmask member of the inheritance
structure and specifying the SPAWN_EXPLICIT_CPU flag when
you call
spawn()
Or:
- using the -C or -R option to the on utility when you launch a program. This also sets the process's inherit mask to the same value.
You can change the runmask for an existing thread or process by:
- using the _NTO_TCTL_RUNMASK or
_NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT command to the
ThreadCtl()
kernel call
Or:
- using the -C or -R option to the slay utility. If you also use the -i option, slay sets the inherit mask to the same value.
For more information, see the Multicore Processing chapter of the QNX Neutrino Programmer's Guide.
