core_affinity_rs icon indicating copy to clipboard operation
core_affinity_rs copied to clipboard

Add NetBSD support

Open mchelaru opened this issue 1 year ago • 9 comments
trafficstars

mchelaru avatar Jul 15 '24 06:07 mchelaru

Thank you for the patch! I tried it, and cargo build succeeds, but cargo test is unhappy:

running 5 tests
test netbsd::tests::test_netbsd_get_affinity_mask ... ok
test netbsd::tests::test_netbsd_set_for_current ... FAILED
test tests::test_set_for_current ... FAILED
test tests::test_get_core_ids ... FAILED
test netbsd::tests::test_netbsd_get_core_ids ... FAILED

failures:

---- netbsd::tests::test_netbsd_set_for_current stdout ----
thread 'netbsd::tests::test_netbsd_set_for_current' panicked at src/lib.rs:665:13:
assertion `left == right` failed
  left: false
 right: true

---- tests::test_set_for_current stdout ----
thread 'tests::test_set_for_current' panicked at src/lib.rs:736:9:
assertion failed: set_for_current(ids[0])

---- tests::test_get_core_ids stdout ----
thread 'tests::test_get_core_ids' panicked at src/lib.rs:726:17:
assertion `left == right` failed
  left: 8
 right: 32
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- netbsd::tests::test_netbsd_get_core_ids stdout ----
thread 'netbsd::tests::test_netbsd_get_core_ids' panicked at src/lib.rs:649:21:
assertion `left == right` failed
  left: 8
 right: 32


failures:
    netbsd::tests::test_netbsd_get_core_ids
    netbsd::tests::test_netbsd_set_for_current
    tests::test_get_core_ids
    tests::test_set_for_current

test result: FAILED. 1 passed; 4 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Can you please take another look at this?

0-wiz-0 avatar Feb 20 '25 11:02 0-wiz-0

Hi wiz@, thank you for you message.

Is the below present in your box sysctl.conf?

security.models.extensions.user_set_cpu_affinity=1

mchelaru avatar Feb 21 '25 09:02 mchelaru

Hi @mchelaru ! I checked, and no, this is set to 0, which I think is the default. When I change it to 1, more tests pass, but some still fail:

---- tests::test_get_core_ids stdout ----
thread 'tests::test_get_core_ids' panicked at src/lib.rs:726:17:
assertion `left == right` failed
  left: 8
 right: 32
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- netbsd::tests::test_netbsd_get_core_ids stdout ----
thread 'netbsd::tests::test_netbsd_get_core_ids' panicked at src/lib.rs:649:21:
assertion `left == right` failed
  left: 8
 right: 32

Any ideas about those? Is there a way to get the tests to pass even with setting the sysctl to 0 or is 1 required? Thank you!

0-wiz-0 avatar Feb 21 '25 09:02 0-wiz-0

Hm, is this just the number of CPUs on the system? Because that would be 32 in my case.

0-wiz-0 avatar Feb 21 '25 09:02 0-wiz-0

Do you happen to build on a non-default processor set? What does psrset output?

mchelaru avatar Feb 21 '25 10:02 mchelaru

The output is:

# psrset
system processor set 0: processor(s) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

0-wiz-0 avatar Feb 21 '25 10:02 0-wiz-0

I think the problem is that cpuset_size() is just a size that is needed for pthread_set_affinity_np() and NOT a CPU count. I think this patch (on top of yours) improves the situation. It also makes the tests pass (with the sysctl still set):

diff --git a/src/lib.rs b/src/lib.rs
index 86f7bd3..cf8532f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -580,6 +580,7 @@ mod netbsd {
         pthread_getaffinity_np, pthread_setaffinity_np, pthread_self, cpuset_t,
         _cpuset_create, _cpuset_size, _cpuset_set, _cpuset_isset, _cpuset_destroy
     };
+    use num_cpus;

     use super::CoreId;

@@ -587,8 +588,8 @@ mod netbsd {
         if let Some(full_set) = get_affinity_mask() {
             let mut core_ids: Vec<CoreId> = Vec::new();

-            let sz = unsafe { _cpuset_size(full_set) };
-            for i in 0..sz {
+            let num_cpus = num_cpus::get();
+            for i in 0..num_cpus {
                 if unsafe { _cpuset_isset(i as u64, full_set) } >= 0 {
                     core_ids.push(CoreId { id: i });
                 }
@@ -668,8 +669,8 @@ mod netbsd {
             // to the specified core.
             let new_mask = get_affinity_mask().unwrap();
             assert!(unsafe { _cpuset_isset(ci.id as u64, new_mask) > 0 });
-            let sz = unsafe { _cpuset_size(new_mask) };
-            for i in 0..sz {
+            let num_cpus = num_cpus::get();
+            for i in 0..num_cpus {
                 if i != ci.id {
                     assert_eq!(0, unsafe { _cpuset_isset(i as u64, new_mask) });
                 }

0-wiz-0 avatar Feb 21 '25 15:02 0-wiz-0

I think you are right, cpuset_size is the size in bytes, and not the size of the set, so it's misused there.

mchelaru avatar Feb 21 '25 17:02 mchelaru

I think this is as good as it will get. On NetBSD, pthread_setaffinity_np needs root privileges or the sysctl set. @Elzair can you please merge this and make a new release?

0-wiz-0 avatar Feb 22 '25 08:02 0-wiz-0

Sorry for the wait. I did not see the notification. My bad. I have merged it and bumped the version number.

Elzair avatar Feb 28 '25 18:02 Elzair

No worries, thank you for merging it and the release. I just noticed the README could do with mentioning NetBSD support - do you want a PR for that? - and there are no tags for 0.8.1 and 0.8.2 on github (though the crates are on crates.io, which is more important anyway).

0-wiz-0 avatar Feb 28 '25 18:02 0-wiz-0

I will add that in a bit. Thanks for the catch!

Elzair avatar Feb 28 '25 19:02 Elzair