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

Fix problem with threaded Zephyr and overflow handling in QEMU emulation #159

Merged
merged 6 commits into from
Feb 17, 2023

Conversation

erlingrj
Copy link
Collaborator

@erlingrj erlingrj commented Feb 15, 2023

This PR addresses various bugs that I discovered when debugging the QEMU emulation of the threaded runtime.

  1. When number of workers were not specified the system could not create any workers through lf_thread_create. Fixed by turning off threading support until we know whether lf_thread_create should be a user-facing API.
  2. In the threaded runtime, the adaptive scheduler was still used because it was missing a #inlude "lf_types.h" at the top.
  3. Some left-over debug-code was using the low-res timer also in the lf_clockgettime implementetion for the hi-res timer.
  4. The implementation of lf_clock_gettime for the low-res timer (which is what is used by QEMU), did not handle overflows which caused the emulation to stop after some

@erlingrj erlingrj requested a review from lhstrh February 15, 2023 19:33
Copy link
Member

@lhstrh lhstrh left a comment

Choose a reason for hiding this comment

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

Left some questions...

core/platform/lf_zephyr_support.c Outdated Show resolved Hide resolved
@@ -367,7 +374,8 @@ int lf_available_cores() {
int lf_thread_create(lf_thread_t* thread, void *(*lf_thread) (void *), void* arguments) {
// Use static id to map each created thread to a
static int tid = 0;


// Make sure we dont try to create too many threads
Copy link
Member

Choose a reason for hiding this comment

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

If lf_thread_create is called in user code, then the number of workers isn't really relevant, is it? Does this really belong here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think it is bad practice to do too much dynamic spawning of threads in a microcontroller setting. You want to avoid dynamic memory allocation if you can. Therefore the stacks and thread control blocks are statically allocated. This puts an upper limit to how many times you can call lf_thread_t. The user can use ordinary calls to zephyrs API to create other threads.

Copy link
Member

Choose a reason for hiding this comment

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

While I don't disagree with you on this, AFAIK, the Zephyr implementation is the only one that does this. My point of criticism has to do with the fact that the function is lf_thread_create not lf_worker_create. Threads and workers are two different things, and you're now looking at the number of workers in the thread creation function, which I think is odd...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hm, I would argue that reactor-c is not a threading library and that user-code should not use the LF threading API. That would make the runtime more attractive for use in these embedded systems where people are wary of using dynamic memory allocation. There is already a lot of that in the runtime though, but theoretically, most of it can be replaced by static allocations.

Copy link
Member

Choose a reason for hiding this comment

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

The function does not have a leading underscore, so it is part of the public API...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Zephyr has a POSIX implementation that we could use temporarily, or we can just turn of threaded support for Zephyr, that is fine with me. With the bodiless reactions we have to make a decision about what is actually going to be part of the user-facing API since those includes must be code-generated. So let's make the right decision there and revisit this later

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure I understand your proposal. Here are some possible solutions that crossed my mind:

  • have a define MAX_THREAD_COUNT and check against that
  • update the docs and have all implementations check against NUMBER_OF_WORKERS
  • rename to _lf_thread_create
  • introduce a lf_worker_create that does the check and then just invokes lf_thread_create
  • ...?

@@ -1031,7 +1031,9 @@ void start_threads() {
LF_PRINT_LOG("Starting %u worker threads.", _lf_number_of_workers);
_lf_thread_ids = (lf_thread_t*)malloc(_lf_number_of_workers * sizeof(lf_thread_t));
for (unsigned int i = 0; i < _lf_number_of_workers; i++) {
lf_thread_create(&_lf_thread_ids[i], worker, NULL);
if (lf_thread_create(&_lf_thread_ids[i], worker, NULL) != 0) {
Copy link
Member

Choose a reason for hiding this comment

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

It seems that the check implemented in lf_thread_create should be done here, at the call site, before even invoking lf_thread_create...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since I have statically allocated the stacks for the threads I have to check it inside lf_thread_create to make sure that it is not called from somewhere else

@erlingrj erlingrj marked this pull request as draft February 16, 2023 20:22
@erlingrj erlingrj changed the title Fix problem with threaded Zephyr when number of workers is not specified Fix problem with threaded Zephyr and overflow handling in QEMU emulation Feb 16, 2023
@erlingrj erlingrj marked this pull request as ready for review February 16, 2023 20:38
@erlingrj erlingrj requested a review from lhstrh February 16, 2023 20:38
@lhstrh lhstrh merged commit 6765392 into main Feb 17, 2023
@lhstrh lhstrh deleted the fix-zephyr-threaded branch February 17, 2023 00:16
@lhstrh lhstrh added the bugfix label Feb 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants