-
Notifications
You must be signed in to change notification settings - Fork 601
unix: add (*CPUSet).Fill helper to enable all CPUs #259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
This PR (HEAD: 9f87bcc) has been imported to Gerrit for code review. Please visit Gerrit at https://go-review.googlesource.com/c/sys/+/698015. Important tips:
|
Message from Gopher Robot: Patch Set 1: (1 comment) Please don’t reply on this GitHub thread. Visit golang.org/cl/698015. |
This PR (HEAD: 79c52c7) has been imported to Gerrit for code review. Please visit Gerrit at https://go-review.googlesource.com/c/sys/+/698015. Important tips:
|
Message from Aleksa Sarai: Patch Set 2: (1 comment) Please don’t reply on this GitHub thread. Visit golang.org/cl/698015. |
Some programs (such as container runtimes) want to reset their CPU affinity if they are spawned by processes with a particular CPU affinity. Container runtimes didn't really have to deal with this issue until Linux 6.2 when the cpuset cgroup was changed to no longer auto-reset CPU affinity in this case. A naive approach to resetting your CPU affinity would be to get the number of CPUs by looking at "/proc/stat" or "/sys/devices/system/cpu" (note that runtime.NumCPU() actually returns the CPU affinity of the process at startup time, which isn't useful for this purpose) and then asking for all of those CPUs. However, sched_setaffinity(2) will silently ignore any CPU bits set in the provided CPUSet if they do not exist or are not enabled in the cpuset cgroup of the process. Unfortunately, setting every possible CPU bit in CPUSet with (*CPUSet).Set() is very inefficient. If it were possible to just memset(0xFF) the CPUSet array, users would be able to reset their CPU affinity very cheaply. However, Go doesn't have a memset primitive that can be used in that way. Obvious solutions like setting the array elements of CPUSet to (^0) do not work because CPUSet is an array of a private newtype and so the compiler complains if you try to use a constant like (^0) without a cast (and we cannot use a cast because the type is private): cannot use ^0 (untyped int constant -1) as "golang.org/x/sys/unix".cpuMask value in assignment (overflows) The only real alternative is to do something quite hacky like: cpuset := unix.CPUSet{} for i := range cpuset { cpuset[i]-- // underflow to 0xFF..FF } ... which is the solution we use in runc. It would be much nicer to have a helper that does this memset for us in a less hacky way, since resetting CPU affinity seems like a fairly common operation. Ref: Linux kernel commit da019032819a ("sched: Enforce user requested affinity") Signed-off-by: Aleksa Sarai <[email protected]>
Message from Aleksa Sarai: Patch Set 3: (1 comment) Please don’t reply on this GitHub thread. Visit golang.org/cl/698015. |
This PR (HEAD: 71871db) has been imported to Gerrit for code review. Please visit Gerrit at https://go-review.googlesource.com/c/sys/+/698015. Important tips:
|
Message from Aleksa Sarai: Patch Set 5: (1 comment) Please don’t reply on this GitHub thread. Visit golang.org/cl/698015. |
Message from Kirill Kolyshkin: Patch Set 5: Code-Review+2 Commit-Queue+1 Please don’t reply on this GitHub thread. Visit golang.org/cl/698015. |
Message from Go LUCI: Patch Set 5: Dry run: CV is trying the patch. Bot data: {"action":"start","triggered_at":"2025-08-28T00:31:00Z","revision":"a946a41b7fba35fb245539fa405fc58b37629cdd"} Please don’t reply on this GitHub thread. Visit golang.org/cl/698015. |
Message from Kirill Kolyshkin: Patch Set 5: -Commit-Queue Please don’t reply on this GitHub thread. Visit golang.org/cl/698015. |
Message from Go LUCI: Patch Set 5: This CL has passed the run Please don’t reply on this GitHub thread. Visit golang.org/cl/698015. |
Message from Go LUCI: Patch Set 5: LUCI-TryBot-Result+1 Please don’t reply on this GitHub thread. Visit golang.org/cl/698015. |
Message from Cherry Mui: Patch Set 5: (1 comment) Please don’t reply on this GitHub thread. Visit golang.org/cl/698015. |
Message from Kirill Kolyshkin: Patch Set 5: (1 comment) Please don’t reply on this GitHub thread. Visit golang.org/cl/698015. |
Message from Cherry Mui: Patch Set 5: (1 comment) Please don’t reply on this GitHub thread. Visit golang.org/cl/698015. |
Some programs (such as container runtimes) want to reset their CPU
affinity if they are spawned by processes with a particular CPU
affinity. Container runtimes didn't really have to deal with this issue
until Linux 6.2 when the cpuset cgroup was changed to no longer
auto-reset CPU affinity in this case.
A naive approach to resetting your CPU affinity would be to get the
number of CPUs by looking at "/proc/stat" or "/sys/devices/system/cpu"
(note that runtime.NumCPU() actually returns the CPU affinity of the
process at startup time, which isn't useful for this purpose) and then
asking for all of those CPUs.
However, sched_setaffinity(2) will silently ignore any CPU bits set in
the provided CPUSet if they do not exist or are not enabled in the
cpuset cgroup of the process. This means that you can reset your CPU
affinity by just setting every CPU bit in CPUSet and passing it to
sched_setaffinity(2).
Unfortunately, setting every CPU bit in CPUSet with (*CPUSet).Set() is
very inefficient. If it were possible to just memset(0xFF) the CPUSet
array, users would be able to reset their CPU affinity even more
cheaply. However, Go doesn't have a memset primitive that can be used in
that way.
Obvious solutions like setting the array elements of CPUSet to (^0) do
not work because CPUSet is an array of a private newtype and so the
compiler complains if you try to use a constant like (^0) without a
cast (and we cannot use a cast because the type is private):
The only real alternative is to do something quite hacky like:
... which is the solution we use in runc.
It would be much nicer to have a helper that does this memset for us in
a less hacky way, since resetting CPU affinity seems like a fairly
common operation.
Ref: Linux kernel commit da019032819a ("sched: Enforce user requested affinity")