static bool
can_set_affinity()
{
pid_t pid = fork();
int status = 0;
if (!pid) {
/* Disable coredumps, because a SIGSYS crash is expected. */
struct rlimit limit = { 0 };
limit.rlim_cur = 1;
limit.rlim_max = 1;
setrlimit(RLIMIT_CORE, &limit);
/* Test the syscall in the child process. */
syscall(SYS_sched_setaffinity, 0, 0, 0);
_exit(0);
} else if (pid < 0) {
return false;
}
if (waitpid(pid, &status, 0) < 0) {
return false;
}
if (WIFSIGNALED(status)) {
/* The child process was terminated by a signal,
* thus the syscall cannot be used.
*/
return false;
}
return true;
}
To check for the availability of the syscall, one can try it in a child process and see if the child is terminated by a signal, e.g. like this:
#include <stdbool.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/wait.h>
static bool rlim_cur = 1; rlim_max = 1; (RLIMIT_ CORE, &limit); SYS_sched_ setaffinity, 0, 0, 0); status) ) {
can_set_affinity()
{
pid_t pid = fork();
int status = 0;
if (!pid) {
/* Disable coredumps, because a SIGSYS crash is expected. */
struct rlimit limit = { 0 };
limit.
limit.
setrlimit
/* Test the syscall in the child process. */
syscall(
_exit(0);
} else if (pid < 0) {
return false;
}
if (waitpid(pid, &status, 0) < 0) {
return false;
}
if (WIFSIGNALED(
/* The child process was terminated by a signal,
* thus the syscall cannot be used.
*/
return false;
}
return true;
}