HadrienG2 / hwlocality

Rust bindings to Open MPI Portable Hardware Locality "hwloc" library, covering version 2.0 and above.
MIT License
20 stars 5 forks source link

Use standard library's ThreadId rather than custom type alias #83

Closed nazar-pc closed 8 months ago

nazar-pc commented 8 months ago

I noticed that right now type ThreadId = hwloc_thread_t type alias is used, while there is already ThreadId in standard library that would ideally be used instead, at least as an option.

HadrienG2 commented 8 months ago

Sadly, there is currently no standard way to go from Rust's standard ThreadId to the operating system's integer TID, which hwloc needs. Per the type's documentation...

ThreadIds are under the control of Rust’s standard library and there may not be any relationship between ThreadId and the underlying platform’s notion of a thread identifier – the two concepts cannot, therefore, be used interchangeably.

...which means that in order to be able to convert from a standard ThreadId to a TID, I would need to build some kind of internal HashMap<ThreadId, TID>, which would require very complicated black magic along the lines of the following:

  1. Inject some hook code on the creation/destruction of every standard Rust thread (which would require some kind of OS-specific magic since std does not expose a hook for this) to record ThreadId -> TID mappings, and find another way to do the conversion for every thread that was created before hwlocality was initialized, possibly option 2 below.
  2. Set up some sort of signal handler that allows me to interrupt live threads in order to run some code on them. When my ThreadId -> TID mapping table does not hit, enumerate OS threads and interrupt all of them (thread enumeration is intrinsically racy, so this may need to be repeated for some time until some reasonable delay has elapsed and we're reasonably sure to know about every OS thread the caller might have cared about), check if they are Rust threads using some magic, and if so run the function that queries their Rust ThreadId. Add the results to our internal ThreadID -> TID mapping table.

Basically, unless the Rust standard library exposes some global knowledge of the mapping from its ThreadIds to OS TIDs (which they probably do not currently have, it will require some work on their side), this will be very hard to achieve and probably should not be done.

For what it's worth, the reason why the rust ThreadId is not a simple TID is that they want it to be unique and never reused, which ironically is a property that is important when building something like the aforementioned mapping.

nazar-pc commented 8 months ago

Is there a way to somehow map std's ThreadId onto OS ThreadId transparently for the user? Especially because thread IDs are unique. For current thread should be a matter of checking current thread to be equal to the requested, but maybe there is a way to query others in a similar way.

If not, at least exposing library API to get current thread ID would be nice such that users of the library do not have to conditionally add libc and windows-sys to their dependencies just for this purpose.

HadrienG2 commented 8 months ago

According to a search for ThreadId in parameter and result types in the std docs, the only circumstances where one can get a pthread_t or similar from a ThreadId is when having access to the JoinHandle of the thread, which is not general enough to be useful I think.

I would be fine with adding some kind of get_current_thread() and get_current_process() to the root of the crate, however. It would also allow removing some platform-specific code from the examples, which is always nice.