| .\" Copyright (C) 2006 Michael Kerrisk |
| .\" and Copyright (C) 2008 Linux Foundation, written by Michael Kerrisk |
| .\" <mtk.manpages@gmail.com> |
| .\" |
| .\" %%%LICENSE_START(VERBATIM) |
| .\" Permission is granted to make and distribute verbatim copies of this |
| .\" manual provided the copyright notice and this permission notice are |
| .\" preserved on all copies. |
| .\" |
| .\" Permission is granted to copy and distribute modified versions of this |
| .\" manual under the conditions for verbatim copying, provided that the |
| .\" entire resulting derived work is distributed under the terms of a |
| .\" permission notice identical to this one. |
| .\" |
| .\" Since the Linux kernel and libraries are constantly changing, this |
| .\" manual page may be incorrect or out-of-date. The author(s) assume no |
| .\" responsibility for errors or omissions, or for damages resulting from |
| .\" the use of the information contained herein. The author(s) may not |
| .\" have taken the same level of care in the production of this manual, |
| .\" which is licensed free of charge, as they might when working |
| .\" professionally. |
| .\" |
| .\" Formatted or processed versions of this manual, if unaccompanied by |
| .\" the source, must acknowledge the copyright and authors of this work. |
| .\" %%%LICENSE_END |
| .\" |
| .TH CPU_SET 3 2021-03-22 "Linux" "Linux Programmer's Manual" |
| .SH NAME |
| CPU_SET, CPU_CLR, CPU_ISSET, CPU_ZERO, CPU_COUNT, |
| CPU_AND, CPU_OR, CPU_XOR, CPU_EQUAL, |
| CPU_ALLOC, CPU_ALLOC_SIZE, CPU_FREE, |
| CPU_SET_S, CPU_CLR_S, CPU_ISSET_S, CPU_ZERO_S, |
| CPU_COUNT_S, CPU_AND_S, CPU_OR_S, CPU_XOR_S, CPU_EQUAL_S \- |
| macros for manipulating CPU sets |
| .SH SYNOPSIS |
| .nf |
| .BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */" |
| .B #include <sched.h> |
| .PP |
| .BI "void CPU_ZERO(cpu_set_t *" set ); |
| .PP |
| .BI "void CPU_SET(int " cpu ", cpu_set_t *" set ); |
| .BI "void CPU_CLR(int " cpu ", cpu_set_t *" set ); |
| .BI "int CPU_ISSET(int " cpu ", cpu_set_t *" set ); |
| .PP |
| .BI "int CPU_COUNT(cpu_set_t *" set ); |
| .PP |
| .BI "void CPU_AND(cpu_set_t *" destset , |
| .BI " cpu_set_t *" srcset1 ", cpu_set_t *" srcset2 ); |
| .BI "void CPU_OR(cpu_set_t *" destset , |
| .BI " cpu_set_t *" srcset1 ", cpu_set_t *" srcset2 ); |
| .BI "void CPU_XOR(cpu_set_t *" destset , |
| .BI " cpu_set_t *" srcset1 ", cpu_set_t *" srcset2 ); |
| .PP |
| .BI "int CPU_EQUAL(cpu_set_t *" set1 ", cpu_set_t *" set2 ); |
| .PP |
| .BI "cpu_set_t *CPU_ALLOC(int " num_cpus ); |
| .BI "void CPU_FREE(cpu_set_t *" set ); |
| .BI "size_t CPU_ALLOC_SIZE(int " num_cpus ); |
| .PP |
| .BI "void CPU_ZERO_S(size_t " setsize ", cpu_set_t *" set ); |
| .PP |
| .BI "void CPU_SET_S(int " cpu ", size_t " setsize ", cpu_set_t *" set ); |
| .BI "void CPU_CLR_S(int " cpu ", size_t " setsize ", cpu_set_t *" set ); |
| .BI "int CPU_ISSET_S(int " cpu ", size_t " setsize ", cpu_set_t *" set ); |
| .PP |
| .BI "int CPU_COUNT_S(size_t " setsize ", cpu_set_t *" set ); |
| .PP |
| .BI "void CPU_AND_S(size_t " setsize ", cpu_set_t *" destset , |
| .BI " cpu_set_t *" srcset1 ", cpu_set_t *" srcset2 ); |
| .BI "void CPU_OR_S(size_t " setsize ", cpu_set_t *" destset , |
| .BI " cpu_set_t *" srcset1 ", cpu_set_t *" srcset2 ); |
| .BI "void CPU_XOR_S(size_t " setsize ", cpu_set_t *" destset , |
| .BI " cpu_set_t *" srcset1 ", cpu_set_t *" srcset2 ); |
| .PP |
| .BI "int CPU_EQUAL_S(size_t " setsize ", cpu_set_t *" set1 \ |
| ", cpu_set_t *" set2 ); |
| .fi |
| .SH DESCRIPTION |
| The |
| .I cpu_set_t |
| data structure represents a set of CPUs. |
| CPU sets are used by |
| .BR sched_setaffinity (2) |
| and similar interfaces. |
| .PP |
| The |
| .I cpu_set_t |
| data type is implemented as a bit mask. |
| However, the data structure should be treated as opaque: |
| all manipulation of CPU sets should be done via the macros |
| described in this page. |
| .PP |
| The following macros are provided to operate on the CPU set |
| .IR set : |
| .TP |
| .BR CPU_ZERO () |
| Clears |
| .IR set , |
| so that it contains no CPUs. |
| .TP |
| .BR CPU_SET () |
| Add CPU |
| .I cpu |
| to |
| .IR set . |
| .TP |
| .BR CPU_CLR () |
| Remove CPU |
| .I cpu |
| from |
| .IR set . |
| .TP |
| .BR CPU_ISSET () |
| Test to see if CPU |
| .I cpu |
| is a member of |
| .IR set . |
| .TP |
| .BR CPU_COUNT () |
| Return the number of CPUs in |
| .IR set . |
| .PP |
| Where a |
| .I cpu |
| argument is specified, it should not produce side effects, |
| since the above macros may evaluate the argument more than once. |
| .PP |
| The first CPU on the system corresponds to a |
| .I cpu |
| value of 0, the next CPU corresponds to a |
| .I cpu |
| value of 1, and so on. |
| No assumptions should be made about particular CPUs being |
| available, or the set of CPUs being contiguous, since CPUs can |
| be taken offline dynamically or be otherwise absent. |
| The constant |
| .B CPU_SETSIZE |
| (currently 1024) specifies a value one greater than the maximum CPU |
| number that can be stored in |
| .IR cpu_set_t . |
| .PP |
| The following macros perform logical operations on CPU sets: |
| .TP |
| .BR CPU_AND () |
| Store the intersection of the sets |
| .I srcset1 |
| and |
| .I srcset2 |
| in |
| .I destset |
| (which may be one of the source sets). |
| .TP |
| .BR CPU_OR () |
| Store the union of the sets |
| .I srcset1 |
| and |
| .I srcset2 |
| in |
| .I destset |
| (which may be one of the source sets). |
| .TP |
| .BR CPU_XOR () |
| Store the XOR of the sets |
| .I srcset1 |
| and |
| .I srcset2 |
| in |
| .I destset |
| (which may be one of the source sets). |
| The XOR means the set of CPUs that are in either |
| .I srcset1 |
| or |
| .IR srcset2 , |
| but not both. |
| .TP |
| .BR CPU_EQUAL () |
| Test whether two CPU set contain exactly the same CPUs. |
| .SS Dynamically sized CPU sets |
| Because some applications may require the ability to dynamically |
| size CPU sets (e.g., to allocate sets larger than that |
| defined by the standard |
| .I cpu_set_t |
| data type), glibc nowadays provides a set of macros to support this. |
| .PP |
| The following macros are used to allocate and deallocate CPU sets: |
| .TP |
| .BR CPU_ALLOC () |
| Allocate a CPU set large enough to hold CPUs |
| in the range 0 to |
| .IR num_cpus\-1 . |
| .TP |
| .BR CPU_ALLOC_SIZE () |
| Return the size in bytes of the CPU set that would be needed to |
| hold CPUs in the range 0 to |
| .IR num_cpus\-1 . |
| This macro provides the value that can be used for the |
| .I setsize |
| argument in the |
| .BR CPU_*_S () |
| macros described below. |
| .TP |
| .BR CPU_FREE () |
| Free a CPU set previously allocated by |
| .BR CPU_ALLOC (). |
| .PP |
| The macros whose names end with "_S" are the analogs of |
| the similarly named macros without the suffix. |
| These macros perform the same tasks as their analogs, |
| but operate on the dynamically allocated CPU set(s) whose size is |
| .I setsize |
| bytes. |
| .SH RETURN VALUE |
| .BR CPU_ISSET () |
| and |
| .BR CPU_ISSET_S () |
| return nonzero if |
| .I cpu |
| is in |
| .IR set ; |
| otherwise, it returns 0. |
| .PP |
| .BR CPU_COUNT () |
| and |
| .BR CPU_COUNT_S () |
| return the number of CPUs in |
| .IR set . |
| .PP |
| .BR CPU_EQUAL () |
| and |
| .BR CPU_EQUAL_S () |
| return nonzero if the two CPU sets are equal; otherwise they return 0. |
| .PP |
| .BR CPU_ALLOC () |
| returns a pointer on success, or NULL on failure. |
| (Errors are as for |
| .BR malloc (3).) |
| .PP |
| .BR CPU_ALLOC_SIZE () |
| returns the number of bytes required to store a |
| CPU set of the specified cardinality. |
| .PP |
| The other functions do not return a value. |
| .SH VERSIONS |
| The |
| .BR CPU_ZERO (), |
| .BR CPU_SET (), |
| .BR CPU_CLR (), |
| and |
| .BR CPU_ISSET () |
| macros were added in glibc 2.3.3. |
| .PP |
| .BR CPU_COUNT () |
| first appeared in glibc 2.6. |
| .PP |
| .BR CPU_AND (), |
| .BR CPU_OR (), |
| .BR CPU_XOR (), |
| .BR CPU_EQUAL (), |
| .BR CPU_ALLOC (), |
| .BR CPU_ALLOC_SIZE (), |
| .BR CPU_FREE (), |
| .BR CPU_ZERO_S (), |
| .BR CPU_SET_S (), |
| .BR CPU_CLR_S (), |
| .BR CPU_ISSET_S (), |
| .BR CPU_AND_S (), |
| .BR CPU_OR_S (), |
| .BR CPU_XOR_S (), |
| and |
| .BR CPU_EQUAL_S () |
| first appeared in glibc 2.7. |
| .SH CONFORMING TO |
| These interfaces are Linux-specific. |
| .SH NOTES |
| To duplicate a CPU set, use |
| .BR memcpy (3). |
| .PP |
| Since CPU sets are bit masks allocated in units of long words, |
| the actual number of CPUs in a dynamically |
| allocated CPU set will be rounded up to the next multiple of |
| .IR "sizeof(unsigned long)" . |
| An application should consider the contents of these extra bits |
| to be undefined. |
| .PP |
| Notwithstanding the similarity in the names, |
| note that the constant |
| .B CPU_SETSIZE |
| indicates the number of CPUs in the |
| .I cpu_set_t |
| data type (thus, it is effectively a count of the bits in the bit mask), |
| while the |
| .I setsize |
| argument of the |
| .BR CPU_*_S () |
| macros is a size in bytes. |
| .PP |
| The data types for arguments and return values shown |
| in the SYNOPSIS are hints what about is expected in each case. |
| However, since these interfaces are implemented as macros, |
| the compiler won't necessarily catch all type errors |
| if you violate the suggestions. |
| .SH BUGS |
| On 32-bit platforms with glibc 2.8 and earlier, |
| .BR CPU_ALLOC () |
| allocates twice as much space as is required, and |
| .BR CPU_ALLOC_SIZE () |
| returns a value twice as large as it should. |
| This bug should not affect the semantics of a program, |
| but does result in wasted memory |
| and less efficient operation of the macros that |
| operate on dynamically allocated CPU sets. |
| These bugs are fixed in glibc 2.9. |
| .\" http://sourceware.org/bugzilla/show_bug.cgi?id=7029 |
| .SH EXAMPLES |
| The following program demonstrates the use of some of the macros |
| used for dynamically allocated CPU sets. |
| .PP |
| .EX |
| #define _GNU_SOURCE |
| #include <sched.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <stdio.h> |
| #include <assert.h> |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| cpu_set_t *cpusetp; |
| size_t size; |
| int num_cpus; |
| |
| if (argc < 2) { |
| fprintf(stderr, "Usage: %s <num\-cpus>\en", argv[0]); |
| exit(EXIT_FAILURE); |
| } |
| |
| num_cpus = atoi(argv[1]); |
| |
| cpusetp = CPU_ALLOC(num_cpus); |
| if (cpusetp == NULL) { |
| perror("CPU_ALLOC"); |
| exit(EXIT_FAILURE); |
| } |
| |
| size = CPU_ALLOC_SIZE(num_cpus); |
| |
| CPU_ZERO_S(size, cpusetp); |
| for (int cpu = 0; cpu < num_cpus; cpu += 2) |
| CPU_SET_S(cpu, size, cpusetp); |
| |
| printf("CPU_COUNT() of set: %d\en", CPU_COUNT_S(size, cpusetp)); |
| |
| CPU_FREE(cpusetp); |
| exit(EXIT_SUCCESS); |
| } |
| .EE |
| .SH SEE ALSO |
| .BR sched_setaffinity (2), |
| .BR pthread_attr_setaffinity_np (3), |
| .BR pthread_setaffinity_np (3), |
| .BR cpuset (7) |