Skip to content
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

sys/posix/pthread: newlib compatibility #17734

Merged

Conversation

gschorcht
Copy link
Contributor

Contribution description

This PR provides a pthread_once_t type that is compatible with newlib's pthread_once_t.

When using a toolchain with built-in POSIX thread support, static C++ constructors use a static (fake) mutex variable which is initialized with pthread_once when first used. However, since RIOT's pthread_once_t type is different from that in newlib's pthread, which is assumed by GCC, RIOT crashes as soon as static constructors are used.

Changing the pthread_once_t type to be compatible with newlib's pthread_once_t type solves the problem and allows the RIOT pthread modules to be used even with toolchains with built-in POSIX thread support. The costs for this change is one additional int variable.

With this change, the precompiled ESP32 toolchains including OpenOCD from Espressif can be used and is no longer necessary to compile them especially for RIOT.

Found out while migrating the ESP32 port to ESP-IDF 4.4, which is the prerequisite for the RIOT port on all different ESP32 SoC variants.

Testing procedure

Compilation in CI should succeed and the tests/pthread* and tests/cpp_ctors should still work. A succeeding test run in CI should be sufficient.

Issues/PRs references

Prerequisite for PR #17601

@github-actions github-actions bot added the Area: sys Area: System label Mar 2, 2022
@gschorcht gschorcht added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR CI: run tests If set, CI server will run tests on hardware for the labeled PR Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation labels Mar 2, 2022
@gschorcht gschorcht force-pushed the sys/posix/pthread_newlib_compatibility branch from bf6a823 to 55ba502 Compare March 2, 2022 09:15
@@ -24,14 +24,17 @@ extern "C" {
/**
* @brief Datatype to supply to pthread_once().
*/
typedef volatile int pthread_once_t;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not really clear to me why pthread_once_t was declared to be volatile, propably to vaoid optimizing it out. But I don't see any reason why it shouldn't be optimized out.

When using a toolchain with built-in POSIX thread support, static C++ constructors use a static mutex variable which is initialized with `pthread_once` when first used. However, since RIOT's `pthread_once_t` type is different from that in newlib's `pthread`, which is assumed by GCC, RIOT crashes as soon as static constructors are used.
Changing the `pthread_once_t` type to be compatible with newlib's `pthread_once_t` type solves the problem and allows the RIOT `pthread` modules to be used even with toolchains with built-in POSIX thread support.
@gschorcht gschorcht force-pushed the sys/posix/pthread_newlib_compatibility branch from 55ba502 to c09d9d8 Compare March 2, 2022 10:58
*/
typedef volatile int pthread_once_t;
typedef struct {
int is_initialized; /**< initialized */
Copy link
Contributor

Choose a reason for hiding this comment

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

So this value is only touched by newlib?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A variable of type pthread_once_t can be used by both user code and the gcc/g++ libraries to ensure that the specified function (the init_routine) is executed only once. However, the value of such a pthread_once_t variable must only be touched by the pthread_once() function. The state of a pthread_once_t variable should not be of interest for code usage.

Before a pthread_once_t variable is used, it must be initialized with PTHREAD_ONCE_INIT. Since the variable was previously a simple int variable, it would be theoretically possible for the user code to initialize it with = 0.But that should now trigger a compilation error.

Copy link
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

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

If Murdock is happy with this, this can go in.

@fjmolinas fjmolinas merged commit 644f32f into RIOT-OS:master Mar 3, 2022
@gschorcht
Copy link
Contributor Author

Thanks for reviewing and merging.

@gschorcht gschorcht deleted the sys/posix/pthread_newlib_compatibility branch March 3, 2022 16:21
@OlegHahm OlegHahm added this to the Release 2022.04 milestone Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: sys Area: System CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR CI: run tests If set, CI server will run tests on hardware for the labeled PR Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants