unix: add CPUSetInterface for variable-size CPU affinity masks
The existing CPUSet type is a fixed-size array limited to 1024 CPUs,
which makes it problematic to use for large systems (see e.g.
https://github.com/opencontainers/runc/issues/5023).
This change introduces CPUSetInterface in an attempt to allow both
the existing CPUSet as well as the variable-size implementation
(see the following commit) to work functions currently accepting CPUSet.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
diff --git a/unix/affinity_linux.go b/unix/affinity_linux.go
index 3ea4703..7ef8c95 100644
--- a/unix/affinity_linux.go
+++ b/unix/affinity_linux.go
@@ -13,11 +13,25 @@
const cpuSetSize = _CPU_SETSIZE / _NCPUBITS
+// CPUSetInterface is an interface for CPU affinity masks.
+// It allows both fixed-size and variable-size CPU sets to be used
+// with affinity functions.
+type CPUSetInterface interface {
+ Zero()
+ Fill()
+ Set(cpu int)
+ Clear(cpu int)
+ IsSet(cpu int) bool
+ Count() int
+ Size() int
+ Pointer() unsafe.Pointer
+}
+
// CPUSet represents a CPU affinity mask.
type CPUSet [cpuSetSize]cpuMask
-func schedAffinity(trap uintptr, pid int, set *CPUSet) error {
- _, _, e := RawSyscall(trap, uintptr(pid), uintptr(unsafe.Sizeof(*set)), uintptr(unsafe.Pointer(set)))
+func schedAffinity(trap uintptr, pid int, set CPUSetInterface) error {
+ _, _, e := RawSyscall(trap, uintptr(pid), uintptr(set.Size()), uintptr(set.Pointer()))
if e != 0 {
return errnoErr(e)
}
@@ -26,13 +40,13 @@
// SchedGetaffinity gets the CPU affinity mask of the thread specified by pid.
// If pid is 0 the calling thread is used.
-func SchedGetaffinity(pid int, set *CPUSet) error {
+func SchedGetaffinity(pid int, set CPUSetInterface) error {
return schedAffinity(SYS_SCHED_GETAFFINITY, pid, set)
}
// SchedSetaffinity sets the CPU affinity mask of the thread specified by pid.
// If pid is 0 the calling thread is used.
-func SchedSetaffinity(pid int, set *CPUSet) error {
+func SchedSetaffinity(pid int, set CPUSetInterface) error {
return schedAffinity(SYS_SCHED_SETAFFINITY, pid, set)
}
@@ -91,3 +105,13 @@
}
return c
}
+
+// Size returns the size of the CPU set in bytes.
+func (s *CPUSet) Size() int {
+ return int(unsafe.Sizeof(*s))
+}
+
+// Pointer returns an unsafe.Pointer to the CPU set.
+func (s *CPUSet) Pointer() unsafe.Pointer {
+ return unsafe.Pointer(s)
+}
diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go
index 06c0eea..497d1da 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -2644,8 +2644,8 @@
//sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error)
//sys Mseal(b []byte, flags uint) (err error)
-//sys setMemPolicy(mode int, mask *CPUSet, size int) (err error) = SYS_SET_MEMPOLICY
+//sys setMemPolicy(mode int, mask unsafe.Pointer, size int) (err error) = SYS_SET_MEMPOLICY
-func SetMemPolicy(mode int, mask *CPUSet) error {
- return setMemPolicy(mode, mask, _CPU_SETSIZE)
+func SetMemPolicy(mode int, mask CPUSetInterface) error {
+ return setMemPolicy(mode, mask.Pointer(), mask.Size())
}
diff --git a/unix/zsyscall_linux.go b/unix/zsyscall_linux.go
index 8935d10..e378761 100644
--- a/unix/zsyscall_linux.go
+++ b/unix/zsyscall_linux.go
@@ -2241,8 +2241,8 @@
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func setMemPolicy(mode int, mask *CPUSet, size int) (err error) {
- _, _, e1 := Syscall(SYS_SET_MEMPOLICY, uintptr(mode), uintptr(unsafe.Pointer(mask)), uintptr(size))
+func setMemPolicy(mode int, mask unsafe.Pointer, size int) (err error) {
+ _, _, e1 := Syscall(SYS_SET_MEMPOLICY, uintptr(mode), uintptr(mask), uintptr(size))
if e1 != 0 {
err = errnoErr(e1)
}
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Commit-Queue | +1 |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
🤖 Generated with [Claude Code](https://claude.com/claude-code)No markdown in commit messages (though I appreciate the code generation disclaimer).
func SchedSetaffinity(pid int, set *CPUSet) error {Unfortunately changing the type of function arguments is not a backwards compatible change. It breaks code using the function as a function value. e.g., https://go.dev/play/p/StqvRpFMU1-
So this would need to be a new API, at which point (IMO) it may as well use CPUSetDynamic directly rather than an interface.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
func SchedSetaffinity(pid int, set *CPUSet) error {Unfortunately changing the type of function arguments is not a backwards compatible change. It breaks code using the function as a function value. e.g., https://go.dev/play/p/StqvRpFMU1-
So this would need to be a new API, at which point (IMO) it may as well use CPUSetDynamic directly rather than an interface.
How would you name new `Sched[GS]etaffinity` and `SetMemPolicy`? Add the `Dynamic` suffix to all of them?
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |