Skip to content

complete out the os.sched_getaffinity error set #6886

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

Closed
wants to merge 17 commits into from
23 changes: 19 additions & 4 deletions lib/std/os.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4432,15 +4432,30 @@ pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void {
}
}

pub const SchedGetAffinityError = error{PermissionDenied} || UnexpectedError;
pub const SchedGetAffinityError = error{
/// The calling thread does not have appropriate privileges.
PermissionDenied,

/// Memory address was invalid.
InvalidAddress,

/// The affinity bit mask mask contains no processors that are currently physically on the system and permitted to the process.
NoProcessors,

/// The thread whose ID is pid could not be found.
NoThread,
} || UnexpectedError;

/// Retrieves the affinity mask of a thread.
///
/// A thread's CPU affinity mask determines the set of CPUs on which it is eligible to run.
pub fn sched_getaffinity(pid: pid_t) SchedGetAffinityError!cpu_set_t {
var set: cpu_set_t = undefined;
switch (errno(system.sched_getaffinity(pid, @sizeOf(cpu_set_t), &set))) {
0 => return set,
EFAULT => unreachable,
EINVAL => unreachable,
ESRCH => unreachable,
EFAULT => return error.InvalidAddress,
EINVAL => return error.NoProcessors,
ESRCH => return error.NoThread,
EPERM => return error.PermissionDenied,
else => |err| return unexpectedErrno(err),
}
Expand Down
9 changes: 9 additions & 0 deletions lib/std/os/test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -601,3 +601,12 @@ test "getrlimit and setrlimit" {
const cpuLimit = try os.getrlimit(.CPU);
try os.setrlimit(.CPU, cpuLimit);
}

test "os.sched_getaffinity" {
// TODO enable for other systems when implemented
// https://github.com/ziglang/zig/issues/6907
if (builtin.os.tag != .linux) {
return error.SkipZigTest;
}
testing.expectError(error.NoThread, os.sched_getaffinity(std.math.maxInt(i32)));
Copy link
Author

@komuw komuw Oct 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My assumption here is that we will never have as many threads as maxInt(i32) when running tests.
But there is a good probability that I'm wrong. Thoughts?

Copy link
Author

@komuw komuw Oct 31, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On windows and Osx, this is failing with

error: use of undeclared identifier 'cpu_set_t'
pub fn sched_getaffinity(pid: pid_t) SchedGetAffinityError!cpu_set_t {

Should I restrict this test to linux only?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On windows and Osx, this is failing with

Welcome to the world of cross-platform non-posix abstractions (and yet another opportunity to plug #6600):

  • NetBSD has pthread_setaffinity_np/pthread_getaffinity_np
  • FreeBSD has cpuset_getaffinity/cpuset_setaffinity
  • macOS has no direct equivalent, thread_policy_get/thread_policy_set let you get/set the affinity tag for a given thread but that's it
  • OpenBSD has no such API (cc @semarie)

My assumption here is that we will never have as many threads as maxInt(i32) when running tests.

That's a pretty safe assumption (why are PIDs signed???), spawning that many threads requires an ungodly amount of memory heh

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have skipped the test for non-linux OSes. I have also opened #6907 to implement sched_getaffinity for other OSes. I'll attempt to do that in a follow up PR, if no one else will have done so already.

}
11 changes: 7 additions & 4 deletions lib/std/thread.zig
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ pub const Thread = struct {
return c.pthread_self();
} else
return switch (std.Target.current.os.tag) {
.linux => os.linux.gettid(),
.windows => windows.kernel32.GetCurrentThreadId(),
else => @compileError("Unsupported OS"),
};
.linux => os.linux.gettid(),
.windows => windows.kernel32.GetCurrentThreadId(),
else => @compileError("Unsupported OS"),
};
}

/// Returns the handle of this thread.
Expand Down Expand Up @@ -479,6 +479,9 @@ pub const Thread = struct {

pub const CpuCountError = error{
PermissionDenied,
InvalidAddress,
NoProcessors,
NoThread,
SystemResources,
Unexpected,
};
Expand Down