Exclude CPU with libc sched_setaffinity

I need my process to run with real-time priority on all CPUs except CPU0.
I set real-time priorities and it looks fine:

fn set_real_time_priority() -> Result<(), String>{
    // Set the real-time priority for the current process
    unsafe {
        let priority = libc::SCHED_FIFO; // or use libc::SCHED_RR for round-robin scheduling
        let max_priority = libc::sched_get_priority_max(libc::SCHED_FIFO);
        let param = libc::sched_param { sched_priority: max_priority };

        let result = libc::sched_setscheduler(0, priority, &param);

        if result == -1 {
            error!("Failed to set real-time priority: {}", std::io::Error::last_os_error());
            return Err("Failed to set real-time priority".to_string());
        } else {
            info!("Real-time priority set successfully!");
        }
        Ok(())
    }
}

I tried to exclude CPU0:

fn set_process_cpu_affinity() {
    unsafe {
        let pid = libc::getpid();

        // Get the number of available CPUs
        let num_cpus = libc::sysconf(libc::_SC_NPROCESSORS_CONF);
        if num_cpus <= 0 {
            eprintln!("Failed to get the number of CPUs: {}", std::io::Error::last_os_error());
            return;
        }

        // Allocate memory for the CPU mask
        let cpus_bytes = libc::CPU_ALLOC_SIZE(num_cpus as i32);
        let cpus_ptr = libc::CPU_ALLOC(num_cpus as usize);
        if cpus_ptr.is_null() {
            eprintln!("Failed to allocate memory for the CPU set: {}", std::io::Error::last_os_error());
            return;
        }

        // Initialize the CPU mask
        libc::CPU_ZERO(cpus_ptr);

        // Enable all CPUs except CPU 0
        for cpu in 1..num_cpus {
            libc::CPU_SET(cpu as usize, cpus_ptr);
        }
        libc::CPU_CLR(0, cpus_ptr);

        // Set CPU affinity for the entire process
        let ret = libc::sched_setaffinity(pid, cpus_bytes, cpus_ptr);

        if ret != 0 {
            eprintln!("Failed to set process CPU affinity: {}", std::io::Error::last_os_error());
        } else {
            println!("Process CPU affinity set successfully!");
        }
    }
}

But got:

cannot find function, tuple struct or tuple variant CPU_ALLOC in crate libc

Is there an equivalent to libc::CPU_ALLOC in rust?

The libc definitions seem to have been built for a world where you could only have CPU_SETSIZE CPUs in your computer, that is, 1024. Unless you need to support more than that, I think you can just use a single cpu_set_t. For a less useful example:

let ret = unsafe {
    let mut cpuset: cpu_set_t = mem::zeroed();
    CPU_SET(1, &mut cpuset);
    sched_setaffinity(getpid(), mem::size_of::<cpu_set_t>(), &cpuset)
};

If you need to support greater than 1024 processors properly, you could use a Vec<cpu_set_t>, calling CPU_SET on the correct element yourself.

1 Like