Go to main content

man pages section 2: System Calls

Exit Print View

Updated: Wednesday, July 27, 2022
 
 

processor_affinity(2)

Name

processor_affinity - control a LWP's affinity for CPUs

Synopsis

#include <sys/processor.h>
#include <sys/procset.h>

int processor_affinity(procset_t
 *ps, uint_t 
*nids, id_t *ids,
    uint32_t *flags);

Description

The processor_affinity() system call determines a LWP (lightweight process) affinity for a set of CPUs and how strictly such affinity should be enforced. Similar to processor bindings, affinities determine on which processor(s) a LWP will be scheduled to execute on, with the advantage of allowing such behavior to be strong or weakly enforced, and with more flexibility when specifying the target processors.

With strong affinity the target LWPs will only run on the specified processors, while weak affinity results in a best effort attempt at executing the LWPs on such CPUs. processor_affinity() also provides more flexibility by allowing users to specify processors in terms of CPUs contained in a Processor Group or Leaf Locality Group, and also in terms of the processors where LWPs should not be scheduled on.

The ps argument identifies for which LWPs the call will be applied to through a procset structure. For details, see procset.h(3HEAD). The flags argument must contain valid combinations of the following options:

PA_QUERY

Query flags and affinities.

PA_CLEAR

Clears any existing affinity.

PA_TYPE_CPU

Indicates that the given IDs are processor IDs, when setting, and that the results of a query should return processor IDs.

PA_TYPE_PG

Indicates that the given IDs are Processor Group IDs, when setting, and that the results of a query should return processor group IDs. Processor group 0 cannot be used.

PA_TYPE_LGRP

Indicates that the given IDs are Locality Group IDs, when setting, and that the results of a query should return locality group IDs. Only the root or leaf lgroups are accepted.

PA_TYPE_CORE

Indicates that the given IDs are core IDs, when setting, and that the results of a query should return corresponding core IDs.

PA_AFF_WEAK

Prefer to run on specified CPUs.

PA_AFF_STRONG

Only run on specified CPUs.

PA_NEGATIVE

Avoid running on specified CPUs, used in conjunction with the affinity strength.

PA_NO_INH_EXEC

Do not inherit affinities across exec(2).

PA_NO_INH_FORK

Do not inherit affinities across fork(2).

PA_NO_INH_THR

Do not inherit affinities across thr_create(3C).

When setting affinities, the nids argument points to a memory position holding the number of CPU, PG, lgroup or core identifiers to which affinity is being set, and ids points to an array with the identifiers. Only one type of affinity must be specified, along with one affinity strength. Negative affinity is a type modifier that indicates that the given IDs should be avoided, and affinity of the specified type should be set to all other processors in the system.

When querying affinities, PA_TYPE_CPU, PA_TYPE_PG, PA_TYPE_CORE, or PA_TYPE_LGRP may be specified as an indication that the returned identifiers must be either those of CPUs, processor groups, locality groups, or cores that contain the processors to which the specified LWPs have affinity for. If no type is specified, the interface defaults to CPUs.

Upon a successful query, nids will contain the number of CPUs, PGs, lgroups, or cores for which the specified LWPs have an affinity. If ids is not NULL, processor_affinity() will store, up to the initial nids value, the IDs of the indicated type. Additionally, flags will return the affinity strength and whether any type of inheritance is excluded.

When clearing affinities, the caller can either specify a set of LWPs that should have their affinities revoked (through the ps argument) or none, and instead specify a list of CPU, PG, lgroup, or core identifiers for which all affinities must be cleared. See EXAMPLES below for details.

Querying, clearing and setting affinities are mutually exclusive operations. Combining such flags results in failure and errno set to EINVAL.

It is important to note that the runtime behavior determined by processor_affinity() is subject to the continued online state of the specified CPUs and their affiliation to the same processor set as the target LWPs. If these underlying conditions change, a LWP will lose its affinity for a given CPU and will need to be reset once the conditions are restored.

When specifying multiple LWPs, these should all be bound to the same processor set (or to none), as LWPs can only have affinity for CPUs contained in their set. Additionally, setting affinities will succeed if processor_affinity() is able to set a LWPs affinity for any of the specified processors, even if a subset of such CPUs may be invalid, offline, or faulted.

processor_bind() and processor_affinity() are implemented by the same mechanism, only differing in the limitations imposed by the number and types of arguments each accepts. This is to say that calls to processor_bind() are essentially calls to processor_affinity() that only allow setting and querying binding to a single CPU at a time.

The {PRIV_PROC_OWNER} privilege must be asserted in the effective set of the calling process or the real or effective user ID of the calling process must match the real or effective user ID of the LWPs being bound. If the calling process does not have permission to change all of the specified LWPs, the bindings of the LWPs for which it does have permission will be changed even though an error is returned.

Return Values

processor_affinity() returns 0 upon successful completion. If an error occurs, -1 is returned and errno is set to indicate its cause.

0

Returns 0 upon successful completion.

-1

Returns -1 upon an error and errno is set to indicate the cause.

Errors

The processor_affinity() function will fail if the following error codes are returned:

ESRCH

None of the specified LWPs exist.

EINVAL

The contents of ps are invalid, one or more CPUs specified through nids and ids are offline, faulted, or the given combination of flags is invalid.

EBADF

One or more CPUs specified through nids and ids are in a different processor set.

EPERM

The {PRIV_PROC_OWNER} privilege is not asserted in the effective set of the calling process and its real or effective user ID does not match the real or effective user ID of one of the LWPs being bound.

Examples

Example 1 Setting Strong Affinity for CPUs [0-3] to the Current LWP
#include <err.h>
#include <libuutil.h>
#include <sys/processor.h>
#include <sys/procset.h>
#include <thread.h>

procset_t ps;
id_t ids[] = { 0, 1, 2, 3 };
uint_t nids = UU_NELEM(ids);
uint32_t flags = PA_TYPE_CPU | PA_AFF_STRONG;

setprocset(&ps, POP_AND, P_PID, P_MYID, P_LWPID, thr_self());

if (processor_affinity(&ps, &nids, ids, &flags) != 0)
        err(1, "Error setting affinity");
Example 2 Setting Weak Affinity for CPUs in Processor Group 3 and 7 to Process 300's LWP 2
#include <err.h>
#include <libuutil.h>
#include <sys/processor.h>
#include <sys/procset.h>

procset_t ps;
id_t ids[] = { 3, 7 };
uint_t nids = UU_NELEM(ids);
uint32_t flags = PA_TYPE_PG | PA_AFF_WEAK;

setprocset(&ps, POP_AND, P_PID, 300, P_LWPID, 2);

if (processor_affinity(&ps, &nids, ids, &flags) != 0)
        err(1, "Error setting affinity");
Example 3 Setting Negative Strong Negative Affinity for all CPUs in lgroup 12 to All of User 323's Processes That Are Running Inside a Zone with id 7
#include <err.h>
#include <libuutil.h>
#include <sys/processor.h>
#include <sys/procset.h>

procset_t ps;
id_t ids[] = { 12 };
uint_t nids = UU_NELEM(ids);
uint32_t flags = PA_TYPE_LGRP | PA_AFF_STRONG | PA_NEGATIVE;

setprocset(&ps, POP_AND, P_UID, 323, P_ZONEID, 7);

if (processor_affinity(&ps, &nids, ids, &flags) != 0)
        err(1, "Error setting affinity");
Example 4 Clearing Affinities of the Current Process
#include <err.h>
#include <sys/processor.h>
#include <sys/procset.h>

procset_t ps;
uint32_t flags = PA_CLEAR;

setprocset(&ps, POP_AND, P_PID, P_MYID, P_ALL, 0);

if (processor_affinity(&ps, NULL, NULL, &flags) != 0)
        err(1, "Error clearing affinity");
Example 5 Clearing All Affinities for CPUs 5 and 7
#include <err.h>
#include <libuutil.h>
#include <sys/processor.h>
#include <sys/procset.h>

id_t ids[] = { 5, 7 };
uint_t nids = UU_NELEM(ids);
uint32_t flags = PA_CLEAR | PA_TYPE_CPU;

if (processor_affinity(NULL, &nids, ids, &flags) != 0)
        err(1, "Error clearing affinity");
Example 6 Querying and Printing Affinities for the Current LWP
#include <err.h>
#include <sys/processor.h>
#include <sys/procset.h>
#include <stdlib.h>
#include <thread.h>

id_t *ids;
procset_t ps;
uint_t i, nids;
uint32_t flags = PA_QUERY;

setprocset(&ps, POP_AND, P_PID, P_MYID, P_LWPID, thr_self());

if (processor_affinity(&ps, &nids, NULL, &flags) != 0)
        err(1, "Error querying number of ids");

if (nids == 0) {
	printf("Current LWP has no affinity set.\n");
	return (0);
}

printf("LWP %u has affinity for %u CPUs.\n", thr_self(), nids);

flags = PA_QUERY;
ids = calloc(nids, sizeof (id_t));

if (processor_affinity(&ps, &nids, ids, &flags) != 0)
        err(1, "Error querying ids");

printf("Current LWP has affinity for the following CPU(s):\n");

for (i = 0; i < nids; i++)
        printf(" %lu", ids[i]);

printf("\n");
Example 7 Setting Strong Affinity for Cores [0-3] to the Current LWP
#include <err.h>
#include <libuutil.h>
#include <sys/processor.h>
#include <sys/procset.h>
#include <thread.h>

procset_t ps;
id_t ids[] = { 0, 1, 2, 3 };
uint_t nids = UU_NELEM(ids);
uint32_t flags = PA_TYPE_CORE | PA_AFF_STRONG;

setprocset(&ps, POP_AND, P_PID, P_MYID, P_LWPID, thr_self());

if (processor_affinity(&ps, &nids, ids, &flags) != 0)
        err(1, "Error setting affinity");

Attributes

See attributes(7) for descriptions of the following attributes:

ATTRIBUTE TYPE
ATTRIBUTE VALUE
Interface Stability
Committed
MT-Level
MT-Safe

See Also

lgrpinfo(1), exec(2), fork(2), processor_bind(2), processor_info(2), pset_bind(2), pset_create(2), thr_create(3C), procset.h(3HEAD), attributes(7), privileges(7), pginfo(8), psradm(8), psrinfo(8), psrset(8)