We need to track the threads ourselves now, but that also lets us act
more intelligently. We know when the thread is detached, so we can
return an error in join before calling libctru. We can also implement
the "retval" functionality of `pthread_join`.
We can't just only keep track of the thread ID, because libctru expects
us to use their `Thread` pointer/data structure.
Had to fix a few compile errors since we switched to using ctru_sys
directly. This is also just the basic support that was there before.
More work needs to be done to support std.
pthread_cond_timedwait gives a timestamp as the timeout, but libctru
expects a duration. After converting the timestamp to nanoseconds since
epoch, we were telling libctru to sleep for over 52 years!
This commit changes our impl to convert the timestamp to a duration.
Additionally, CondVar_WaitTimeout returns a boolean indicating if it
timed out or not. But pthread_cond_timedwait expects a libc-style error
code. This conversion is added as well.
The standard library RwLock checks if it's panicking while making the
guard. This check needs to use a thread local key, which it lazily
creates. This causes reentrant/recursive locking, which leads to a
deadlock.
This commit replaces the std RwLock with one from spin, which does not
need to check thread local storage to lock. It's a spin-lock, but it is
configured to yield the thread on every unsuccessful spin. Also, the
lock can be created statically, which means we don't need once_cell.
An alternative to spin is parking_lot, but that has some compile errors
(it wants condvars to support monotonic clocks) and brings in more
dependencies.