Objects are normally designed and built so that they can execute on all systems of a given architecture. However, individual systems, with special capabilities, are often targeted for optimization. Optimized code can be identified with the capabilities that the code requires to execute, using the mechanisms described in the previous sections.
To exercise and test optimized instances it is necessary to use a system that provides the required capabilities. For each system, the runtime linker determines the capabilities that are available, and then chooses the most capable instances. To aid testing and experimentation, the runtime linker can be told to use an alternative set of capabilities than those provided by the system. In addition, you can specify that only specific files should be validated against these alternative capabilities.
An alternative set of capabilities is derived from the system capabilities, and can be re-initialized or have capabilities added or removed.
A family of environment variables is available to create and target the use of an alternative set of capabilities.
Identifies an alternative platform name.
Identifies an alternative machine hardware name.
Identifies an alternative hardware capabilities value.
Identifies an alternative software capabilities value.
Identifies the files that should be validated against the alternative capabilities.
The capabilities environment variables LD_PLATCAP and LD_MACHCAP accept a string that defines the platform name and machine hardware names respectively. See Identifying a Platform and Machine Capability.
The capabilities environment variables LD_HWCAP and LD_SFCAP accept a comma separated list of tokens as a symbolic representation of capabilities. See Identifying Hardware Capabilities, and Identifying Software Capabilities. A token can also be a numeric value. To provide for setting numeric values for different masks, such as CA_SUNW_HW_1 and CA_SUNW_HW_2, the number can be prefixed with a bracketed index. For example, LD_HWCAP=0x80 sets CA_SUNW_HW_2 to the value 0x80. If no index is specified, 1 is assumed. Invalid indexes are ignored.
A "+" prefix results in the capabilities that follow being added to the alternative capabilities. A "-" prefix results in the capabilities that follow being removed from the alternative capabilities. The lack of "+-" result in the capabilities that follow replacing the alternative capabilities.
The removal of a capability results in a more restricted capabilities environment being emulated. Normally, when a family of capabilities instances is available, a generic, non-capabilities specific instance is also provided. A more restricted capabilities environment can therefore be used to force the use of less capable, or generic code instances.
The addition of a capability results in a more enhanced capabilities environment being emulated. This environment should be created with caution, but can be used to exercise the framework of a capabilities family. For example, a family of functions can be created that define their expected capabilities using mapfiles. These functions can use printf(3C) to confirm their execution. The creation of the associated objects can then be validated and exercised with various capability combinations. This prototyping of a capabilities family can prove useful before the real capabilities requirements of the functions are coded. However, if the code within a family instance requires a specific capability to execute correctly, and this capability is not provided by the system, but is set as an alternative capability, the code instance will fail to execute correctly.
Establishing a set of alternative capabilities without also using LD_CAP_FILES results in all of the capabilities specific objects of a process being validated against the alternative capabilities. This approach should also be exercised with caution, as many system objects require system capabilities to execute correctly. Any alteration of capabilities can cause system objects to fail to execute correctly.
A best environment for capabilities experimentation is to use a system that provides all the capabilities your objects are targeted to use. LD_CAP_FILES should also be used to isolate the objects you wish to experiment with. Capabilities can then be disabled, using the "-" syntax, so that the various instances of your capabilities family can be exercised. Each instance is fully supported by the true capabilities of the system.
For example, suppose you have two x86 capabilities objects, libfoo.so and libbar.so. These objects contain capability functions that use SSE2 instructions, functions that use MMX instructions, and generic functions that require no capabilities. The underlying system provides both SSE2 and MMX. By default, the SSE2 functions are used.
libfoo.so and libbar.so can be restricted to use the functions that use MMX instructions by removing the SSE2 capability by using a LD_HWCAP definition. The most flexible means of defining LD_CAP_FILES is to use the base name of the required files.
$ LD_HWCAP=-sse2 LD_CAP_FILES=libfoo.so,libbar.so ./main
libfoo.so and libbar.so can be further restricted to use only generic functions by removing the SSE2 and MMX capabilities.
$ LD_HWCAP=-sse2,mmx LD_CAP_FILES=libfoo.so,libbar.so ./main
$ LD_DEBUG=basic LD_HWCAP=-sse2,mmx,cx8 ./main .... 02328: hardware capabilities (CA_SUNW_HW_1) - 0x5c6f \ [ SSE3 SSE2 SSE FXSR MMX CMOV SEP CX8 TSC FPU ] 02328: alternative hardware capabilities (CA_SUNW_HW_1) - 0x4c2b \ [ SSE3 SSE FXSR CMOV SEP TSC FPU ] ....