From ec6e0fa5f43a11015feac39b4c0fc8df5d54ebc6 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Thu, 12 May 2022 07:22:57 -0700 Subject: [PATCH] Wrap sched_getaffinity Fixes #385 --- libc/calls/internal.h | 1 + libc/calls/sched_getaffinity.c | 45 ++++++++++++++++++++++++ libc/calls/sched_setaffinity.c | 13 ++++--- libc/runtime/getcpucount.c | 5 ++- libc/sysv/calls/sched_getaffinity.s | 2 -- libc/sysv/calls/sys_sched_getaffinity.s | 2 ++ libc/sysv/syscalls.sh | 2 +- test/libc/calls/sched_getaffinity_test.c | 33 +++++++++++++++++ 8 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 libc/calls/sched_getaffinity.c delete mode 100644 libc/sysv/calls/sched_getaffinity.s create mode 100644 libc/sysv/calls/sys_sched_getaffinity.s create mode 100644 test/libc/calls/sched_getaffinity_test.c diff --git a/libc/calls/internal.h b/libc/calls/internal.h index 50c0e3a85..286b1cd1a 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -229,6 +229,7 @@ i64 sys_pwritev(i32, const struct iovec *, i32, i64, i64) hidden; i64 sys_read(i32, void *, u64) hidden; i64 sys_readlink(const char *, char *, u64) hidden; i64 sys_readlinkat(int, const char *, char *, u64) hidden; +i64 sys_sched_getaffinity(i32, u64, void *) hidden; i64 sys_sendfile(i32, i32, i64 *, u64) hidden; i64 sys_splice(i32, i64 *, i32, i64 *, u64, u32) hidden; i64 sys_vmsplice(i32, const struct iovec *, i64, u32) hidden; diff --git a/libc/calls/sched_getaffinity.c b/libc/calls/sched_getaffinity.c new file mode 100644 index 000000000..023b217c3 --- /dev/null +++ b/libc/calls/sched_getaffinity.c @@ -0,0 +1,45 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" +#include "libc/str/str.h" + +/** + * Gets kernel scheduling for particular CPUs. + * + * @param pid is the process or thread id (or 0 for caller) + * @param size is byte length of bitset + * @param bitset receives bitset and should be uint64_t[16] in order to + * work on older versions of Linux + * @return 0 on success, or -1 w/ errno + * @raise ENOSYS on non-Linux + */ +int sched_getaffinity(int tid, size_t size, void *bitset) { + long rc; + rc = sys_sched_getaffinity(tid, size, bitset); + if (rc != -1) { + if (rc < size) { + memset((char *)bitset + rc, 0, size - rc); + } + rc = 0; + } + STRACE("sched_getaffinity(%d, %'zu, %p) → %d% m", tid, size, bitset); + return rc; +} diff --git a/libc/calls/sched_setaffinity.c b/libc/calls/sched_setaffinity.c index f1c8df0cd..99d6db694 100644 --- a/libc/calls/sched_setaffinity.c +++ b/libc/calls/sched_setaffinity.c @@ -19,6 +19,7 @@ #include "libc/bits/safemacros.internal.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/dce.h" #include "libc/limits.h" #include "libc/nt/enum/processaccess.h" @@ -63,14 +64,18 @@ static textwindows dontinline int sys_sched_setaffinity_nt(int pid, /** * Asks kernel to only schedule process on particular CPUs. * - * @param pid is the process or thread id (or 0 for caller) + * @param tid is the process or thread id (or 0 for caller) * @param bitsetsize is byte length of bitset * @return 0 on success, or -1 w/ errno + * @raise ENOSYS if not Linux or Windows */ -int sched_setaffinity(int pid, uint64_t bitsetsize, const void *bitset) { +int sched_setaffinity(int tid, uint64_t bitsetsize, const void *bitset) { + int rc; if (!IsWindows()) { - return sys_sched_setaffinity(pid, bitsetsize, bitset); + rc = sys_sched_setaffinity(tid, bitsetsize, bitset); } else { - return sys_sched_setaffinity_nt(pid, bitsetsize, bitset); + rc = sys_sched_setaffinity_nt(tid, bitsetsize, bitset); } + STRACE("sched_setaffinity(%d, %'zu, %p) → %d% m", tid, bitsetsize, bitset); + return rc; } diff --git a/libc/runtime/getcpucount.c b/libc/runtime/getcpucount.c index bde181330..7b870d806 100644 --- a/libc/runtime/getcpucount.c +++ b/libc/runtime/getcpucount.c @@ -36,9 +36,8 @@ static unsigned GetCpuCountLinux(void) { uint64_t s[16]; unsigned i, c, n; - if ((n = sched_getaffinity(0, sizeof(s), s)) > 0) { - assert(!(n & 7)); - for (n >>= 3, c = i = 0; i < n; ++i) { + if (!sched_getaffinity(0, sizeof(s), s)) { + for (c = i = 0; i < ARRAYLEN(s); ++i) { c += popcnt(s[i]); } return c; diff --git a/libc/sysv/calls/sched_getaffinity.s b/libc/sysv/calls/sched_getaffinity.s deleted file mode 100644 index 09b2dc8a9..000000000 --- a/libc/sysv/calls/sched_getaffinity.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall sched_getaffinity,0xfffffffffffff0cc,globl diff --git a/libc/sysv/calls/sys_sched_getaffinity.s b/libc/sysv/calls/sys_sched_getaffinity.s new file mode 100644 index 000000000..fd8de6319 --- /dev/null +++ b/libc/sysv/calls/sys_sched_getaffinity.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sched_getaffinity,0xfffffffffffff0cc,globl,hidden diff --git a/libc/sysv/syscalls.sh b/libc/sysv/syscalls.sh index bbd647557..8c4ff493d 100755 --- a/libc/sysv/syscalls.sh +++ b/libc/sysv/syscalls.sh @@ -234,7 +234,7 @@ scall lgetxattr 0x17bffffffffff0c0 globl scall llistxattr 0x17effffffffff0c3 globl scall lremovexattr 0x181ffffffffff0c6 globl scall sys_sched_setaffinity 0xfffffffffffff0cb globl hidden -scall sched_getaffinity 0xfffffffffffff0cc globl # returns bytes written on success. we polyfill bad posix designs like nice() returning 0, but we won't polyfill a bad unilateral redesign that's just glibc +scall sys_sched_getaffinity 0xfffffffffffff0cc globl hidden # returns bytes written on success. we polyfill bad posix designs like nice() returning 0, but we won't polyfill a bad unilateral redesign that's just glibc scall cpuset_getaffinity 0xffffff1e7fffffff globl scall cpuset_setaffinity 0xffffff1e8fffffff globl scall io_setup 0xfffffffffffff0ce globl diff --git a/test/libc/calls/sched_getaffinity_test.c b/test/libc/calls/sched_getaffinity_test.c new file mode 100644 index 000000000..9edeb580b --- /dev/null +++ b/test/libc/calls/sched_getaffinity_test.c @@ -0,0 +1,33 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/popcnt.h" +#include "libc/calls/calls.h" +#include "libc/dce.h" +#include "libc/testlib/testlib.h" + +void SetUp(void) { + if (!IsLinux()) { + exit(0); + } +} + +TEST(sched_getaffinity, test) { + uint64_t s[16]; + EXPECT_SYS(0, 0, sched_getaffinity(0, sizeof(s), &s)); +}