-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Special Thread Builder Functions for the Nintendo 3DS #71
Comments
I'd like to propose changing this in one of two ways. One would be simple but non-portable, the other has the possibility of being a portable API useful in many cases. The simple approach: if we add these in their current form, we should name them something Horizon-specific, so that their names don't conflict with other methods we might add for portable versions of comparable concepts. For instance, However, the portable version I'd love to see: Could we design an abstraction for setting thread (and process, though Horizon may not have that) affinity? On Horizon, the only valid affinities would be single-CPU affinities, Horizon would define constants for those single CPUs, and the default affinity if not set could be the "default core" mentioned above. Other systems would support multi-CPU affinities, and the default would be "all CPUs". Similarly, we could have an abstraction for setting thread (and process) priority. The valid range of priority values, and the default, would need to be target-specific, though we could provide constants for them. (Things like "realtime priority" or "idle priority" might need to be target-specific extensions, but we could map this to nice-level on POSIX.) |
@joshtriplett what do you think about this alternative design? Nothing set in stone, but kind of a sketch of the more portable API I think you had in mind. @AzureMarker @Meziu also curious for your feedback on this as well: Public APIs
|
That looks like a good start to me. The only concerns I have are:
|
This design looks largely reasonable to me. I'd love to see this extended to Linux, using CPU sets, to make sure that the interface works just as well for affinities consisting of multiple CPUs. I agree that the OS-specific details shouldn't be in @AzureMarker I don't think this should use |
The main reason I had it like this was that the existing
I think this is possible, but I can work on a proof of concept to show that it actually is viable this way. Regarding
use crate::sys::unix::thread as imp;
pub struct Priority(imp::Priority);
impl TryFrom<i32> for Priority {}
impl From<Priority> for crate::thread::Priority {} The downside would be another layer of indirection (now we have I suppose to support CPU sets etc., this kind of thing might be necessary anyway? |
I've opened a draft roughly implementing some of my proposed changes in rust-lang/rust#101222 I ended up just making There's a lot of cleanup and stuff that would be needed if this proposal is accepted, but I think this shows that it can work at least for these platforms. It might be good to get some opinions from people who are more familiar with other platforms like Windows to make sure this would be feasible for those as well? |
Closing in favor of #195 |
Proposal
Problem statement
(some background first)
The Nintendo 3DS is supported as a Tier 3 target (
armv6k-nintendo-3ds
). Recently, basic std support was merged in rust-lang/rust#95897. There is now an open PR to enablestd::thread
support: rust-lang/rust#98514.The Nintendo 3DS has a few physical cores that can be used by user applications (2-4 depending on the model1). One of these cores is preemptive (primarily used by the OS, named system core or syscore), and the rest are cooperative (known as app cores). Threads live on the core they were created on, and don't move across cores. See https://www.3dbrew.org/wiki/Multi-threading.
Now coming to the real problem statement: The API used to spawn threads on the 3DS requires the core/processor where the thread will live, as well as the thread priority. The processor ID can't be changed after the thread has been created2, though the priority technically can be (but it should be set at thread creation time). The current Rust thread builder API doesn't provide a way to set the processor ID or priority during thread creation.
Motivation, use-cases
Setting the processor ID is important to 3DS applications. To use the system core, which is preemptive, the correct processor ID needs to be passed during thread creation. To spawn threads on a different core than the main thread, the program needs a way to set the processor ID to use.
There is a processor ID value that tells the 3DS to spawn the thread on the "default" core for the application, but if we use this value, we limit the application to just one core (and it can't use the preemptive system core).
Setting the priority is also important to 3DS applications. Since most of the cores are cooperative, the priority value tells the 3DS what order to executes threads in when a yield happens. Having the wrong priority value could mean lower performance (less opportunities to run the thread). There is an API to get the current thread's priority, which can be used to set new threads to the current thread's priority, so this isn't as big of an issue as the processor ID section. However, since the priority is passed in a thread creation we should have an API to let the user take advantage of this.
Solution sketches
To work around the missing APIs for setting processor ID and priority during thread creation, the
std::thread
PR adds a 3DS target specific extension traitstd::os::horizon::thread::BuilderExt
behind a feature flag which adds support for setting the processor ID and priority:To implement this, the
Builder
struct gets a new crate-privatenative_options
field whose type is platform specific:Since this is a crate/std private field, there is no user facing change to the thread builder outside of the 3DS target. The
native_options
fields are used during thread creation, for example insys/unix/thread.rs
Thread::new
:Alternatively, we could add this API to all platforms, but I don't think most platforms let you set things like the processor ID during thread creation, so this alternative solution probably wouldn't work.
Links and related work
std::thread
PR for the 3DS, which implements the proposed solution behind a feature flag: rust-lang/rust#98514What happens now?
This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.
Footnotes
https://www.3dbrew.org/wiki/Hardware ↩
Technically there are APIs which seem to provide this functionality (setting/getting thread core affinity, fields in the kernel's thread representation), but they don't seem to work. Either way, threads don't seem to automatically load balance. ↩
The text was updated successfully, but these errors were encountered: