Skip to content

Extend cpu affinity mask to support up to 64 cores#286

Open
shegazyy wants to merge 3 commits into
eclipse-score:mainfrom
Valeo-S-CORE-Organization:fix/extend_runmask_to_64_cores
Open

Extend cpu affinity mask to support up to 64 cores#286
shegazyy wants to merge 3 commits into
eclipse-score:mainfrom
Valeo-S-CORE-Organization:fix/extend_runmask_to_64_cores

Conversation

@shegazyy

@shegazyy shegazyy commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

The cpu_mask_ field in OsalConfig and the setaffinity() function used uint32_t, limiting process affinity to at most 32 cores. Systems with more than 32 cores would silently use only the lower 32 bits.

Change the mask type to uint64_t throughout the affected chain:

  • OsalConfig::cpu_mask_ (iprocess.hpp)
  • setaffinity() signature (set_affinity.hpp and both platform impls)
  • kDefaultProcessorAffinityMask() return type (configuration_manager)
  • kDefaultNumCores cap raised from 32 to 64 (num_cores.hpp)

On Linux the loop variable and shift literal are updated to uint64_t / 1ULL to avoid the undefined behaviour for i >= 32 noted in the original review discussion (PR #113).

On QNX the 32-bit ThreadCtl(_NTO_TCTL_RUNMASK_GET_AND_SET) is replaced with _NTO_TCTL_RUNMASK64_GET_AND_SET which accepts a uint64_t mask.

kDefaultProcessorAffinityMask() guards against the n == 64 edge case (where 1ULL << 64 would itself be UB) by returning UINT64_MAX instead.

The XML configuration reader is updated to use std::stoull so the full 64-bit coremask value is parsed without truncation.

Closes #122

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

License Check Results

🚀 The license check job ran with the Bazel command:

bazel run --lockfile_mode=error //:license-check

Status: ⚠️ Needs Review

Click to expand output
[License Check Output]
Extracting Bazel installation...
Starting local Bazel server (8.6.0) and connecting to it...
INFO: Invocation ID: 99d4a756-3391-431e-9af9-85711363d9da
Computing main repo mapping: 
Computing main repo mapping: 
Loading: 
Loading: 0 packages loaded
Loading: 0 packages loaded
Loading: 0 packages loaded
    currently loading: 
Loading: 0 packages loaded
    currently loading: 
Loading: 0 packages loaded
    currently loading: 
Analyzing: target //:license-check (1 packages loaded, 0 targets configured)
Analyzing: target //:license-check (1 packages loaded, 0 targets configured)

Analyzing: target //:license-check (31 packages loaded, 10 targets configured)

Analyzing: target //:license-check (76 packages loaded, 10 targets configured)

Analyzing: target //:license-check (87 packages loaded, 10 targets configured)

Analyzing: target //:license-check (144 packages loaded, 2767 targets configured)

Analyzing: target //:license-check (152 packages loaded, 5482 targets configured)

Analyzing: target //:license-check (152 packages loaded, 5482 targets configured)

Analyzing: target //:license-check (159 packages loaded, 8222 targets configured)

Analyzing: target //:license-check (159 packages loaded, 8222 targets configured)

Analyzing: target //:license-check (164 packages loaded, 8261 targets configured)

Analyzing: target //:license-check (164 packages loaded, 8271 targets configured)

Analyzing: target //:license-check (167 packages loaded, 10159 targets configured)

Analyzing: target //:license-check (167 packages loaded, 10159 targets configured)

Analyzing: target //:license-check (168 packages loaded, 10283 targets configured)

INFO: Analyzed target //:license-check (169 packages loaded, 10409 targets configured).
[12 / 16] JavaToolchainCompileClasses external/rules_java+/toolchains/platformclasspath_classes; 0s disk-cache, processwrapper-sandbox ... (2 actions running)
[14 / 16] JavaToolchainCompileBootClasspath external/rules_java+/toolchains/platformclasspath.jar; 0s disk-cache, processwrapper-sandbox
INFO: Found 1 target...
Target //:license.check.license_check up-to-date:
  bazel-bin/license.check.license_check
  bazel-bin/license.check.license_check.jar
INFO: Elapsed time: 26.304s, Critical Path: 2.65s
INFO: 16 processes: 12 internal, 3 processwrapper-sandbox, 1 worker.
INFO: Build completed successfully, 16 total actions
INFO: Running command line: bazel-bin/license.check.license_check ./formatted.txt <args omitted>
usage: org.eclipse.dash.licenses.cli.Main [-batch <int>] [-cd <url>]
       [-confidence <int>] [-ef <url>] [-excludeSources <sources>] [-help] [-lic
       <url>] [-project <shortname>] [-repo <url>] [-review] [-summary <file>]
       [-timeout <seconds>] [-token <token>]

@shegazyy

shegazyy commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Hey @NicolasFussberger 🙏 ready for review whenever you have a moment!

@NicolasFussberger

Copy link
Copy Markdown
Contributor

Hey @NicolasFussberger 🙏 ready for review whenever you have a moment!

Thanks! I requested @SimonKozik to do a review, he already had a closer look at this some time in the past.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

The created documentation from the pull request is available at: docu-html

@SimonKozik SimonKozik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks OK

@shegazyy shegazyy temporarily deployed to workflow-approval July 6, 2026 13:57 — with GitHub Actions Inactive
@shegazyy shegazyy temporarily deployed to workflow-approval July 6, 2026 13:57 — with GitHub Actions Inactive
@NicolasFussberger

Copy link
Copy Markdown
Contributor

The qnx8 pipeline fails with

 score/launch_manager/src/daemon/src/osal/details/qnx/set_affinity.cpp: In function 'int32_t score::lcm::internal::osal::setaffinity(uint64_t)':
score/launch_manager/src/daemon/src/osal/details/qnx/set_affinity.cpp:30:27: error: '_NTO_TCTL_RUNMASK64_GET_AND_SET' was not declared in this scope
   30 |     return 0 == ThreadCtl(_NTO_TCTL_RUNMASK64_GET_AND_SET, &cpumask) ? 0 : -1;
      |  

I also could not find a reference to _NTO_TCTL_RUNMASK64_GET_AND_SET.

But I think also the runmask support in qnx8 changed significantly with the introduction of cpu clusters.
Do you have any suggestion how to proceed here?

@NicolasFussberger NicolasFussberger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

see above

@shegazyy shegazyy requested a deployment to workflow-approval July 6, 2026 15:38 — with GitHub Actions Waiting
@shegazyy shegazyy requested a deployment to workflow-approval July 6, 2026 15:38 — with GitHub Actions Waiting
@shegazyy

shegazyy commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for catching this @NicolasFussberger 🙏 turns out _NTO_TCTL_RUNMASK64_GET_AND_SET is a QNX 7.x constant that got removed in QNX 8 when the CPU cluster model changed. Added an #ifdef guard so QNX 7 keeps the 64-bit path and QNX 8 falls back to the 32-bit mask (functionally no worse than before this PR). Full 64-core support on QNX 8 with the cluster API can be a follow-up issue. Should fix the QNX 8 build!

Comment thread score/launch_manager/src/daemon/src/osal/details/qnx/set_affinity.cpp Outdated
@shegazyy shegazyy force-pushed the fix/extend_runmask_to_64_cores branch from 3966871 to 195e81f Compare July 8, 2026 12:33
@shegazyy shegazyy temporarily deployed to workflow-approval July 8, 2026 12:33 — with GitHub Actions Inactive
@shegazyy shegazyy temporarily deployed to workflow-approval July 8, 2026 12:33 — with GitHub Actions Inactive
@shegazyy

shegazyy commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Hey @NicolasFussberger 🙏 reworked it to use _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT with the multi-cluster runmask struct, so full 64-core support on QNX 8 with no QNX 7 dead code. Ready for another look!

@shegazyy shegazyy requested a deployment to workflow-approval July 13, 2026 10:50 — with GitHub Actions Waiting
@shegazyy shegazyy requested a deployment to workflow-approval July 13, 2026 10:50 — with GitHub Actions Waiting
@shegazyy shegazyy requested a deployment to workflow-approval July 13, 2026 14:21 — with GitHub Actions Waiting
@shegazyy shegazyy requested a deployment to workflow-approval July 13, 2026 14:21 — with GitHub Actions Waiting
shegazyy added 2 commits July 15, 2026 16:26
The cpu_mask_ field in OsalConfig and the setaffinity() function used
uint32_t, limiting process affinity to at most 32 cores. Systems with
more than 32 cores would silently use only the lower 32 bits.

Change the mask type to uint64_t throughout the affected chain:
- OsalConfig::cpu_mask_ (iprocess.hpp)
- setaffinity() signature (set_affinity.hpp and both platform impls)
- kDefaultProcessorAffinityMask() return type (configuration_manager)
- kDefaultNumCores cap raised from 32 to 64 (num_cores.hpp)

On Linux the loop variable and shift literal are updated to uint64_t /
1ULL to avoid the undefined behaviour for i >= 32 noted in the original
review discussion (PR eclipse-score#113).

On QNX the 32-bit ThreadCtl(_NTO_TCTL_RUNMASK_GET_AND_SET) is replaced
with _NTO_TCTL_RUNMASK64_GET_AND_SET which accepts a uint64_t mask.

kDefaultProcessorAffinityMask() guards against the n == 64 edge case
(where 1ULL << 64 would itself be UB) by returning UINT64_MAX instead.

The XML configuration reader is updated to use std::stoull so the full
64-bit coremask value is parsed without truncation.

Closes eclipse-score#122
_NTO_TCTL_RUNMASK_GET_AND_SET returns EINVAL on systems with more
than 32 CPUs. Use _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT instead,
which accepts a struct _thread_runmask with RMSK_SIZE/RMSK_SET macros
to support up to 64 CPUs across multiple CPU clusters.

Issue: eclipse-score#122
Without setting inherit_mask, only the main thread of the launched
process gets the CPU affinity from _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT.
Any threads spawned by the child will run unconstrained. Setting
inherit_mask mirrors the Linux sched_setaffinity behavior where the
affinity applies to all threads.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

Improvement: Extend LaunchManager to support runmask for 64 cores

3 participants