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

calling os routines before scheduler is started #64

Open
LnnrtS opened this issue Jan 6, 2021 · 13 comments
Open

calling os routines before scheduler is started #64

LnnrtS opened this issue Jan 6, 2021 · 13 comments

Comments

@LnnrtS
Copy link
Contributor

LnnrtS commented Jan 6, 2021

What is the expected behavior when calling os routines before the scheduler is started? From my experience, everything related to memory allocation is working correctly by design, some is not working (sysclock.sleep_for()) and some might just be working by coincidence (this_thread, interaction with mutex). Can you shed some light on this?

This has practical relevance because there are multiples ways how application code is able to call os routines before the scheduler is started. Some of them are hooks like os_startup_initialize_hardware() but also constructors of objects with static storage duration. In the first case it might be obvious to the user that the code is running under special conditions and it's acceptable it has to comply to certain conventions (not calling certain functions); but not in second case.

My concrete suggestions would be

  • detect calls to os routines that happen before the scheduler has started (where this is not already the case)
  • call os_run_init_array() from the main thread

Looking forward to hearing your thoughts on this

@ilg-ul
Copy link
Contributor

ilg-ul commented Jan 6, 2021

What is the expected behavior when calling os routines before the scheduler is started?

Some will run, some will not ;-)

detect calls to os routines that happen before the scheduler has started

I think that this is an useful suggestion, and some asserts should be added to detect calls that should not happen before the scheduler started

call os_run_init_array() from the main thread

I did not check, but the C/C++ standard might require for the static constructors to be called before entering main().

Anyway, having constructors with a complex functional logic (either system calls or touching the hardware) is not a good idea, and should be avoided.

@ilg-ul
Copy link
Contributor

ilg-ul commented Jan 6, 2021

BTW, if I remember right, there might be some calls that switch to a limited functionality when running without the scheduler.

And, if there are not, there should be. In the new version of the project template it is possible to create projects without the scheduler, but there are many calls, even timer.sleep() calls, that do not depend on the scheduler, and can run very well.

The conclusion is that the entire system will need a thorough check and functions that can run without a scheduler, should run, and functions that should not be called without a scheduler should throw an assert.

@LnnrtS
Copy link
Contributor Author

LnnrtS commented Jan 6, 2021

but the C/C++ standard might require for the static constructors to be called before entering main()

Why not have main also run from a thread?
If os_main was just named main (and main renamed to something else) that seems like already solved.

Anyway, having constructors with a complex functional logic (either system calls or touching the hardware) is not a good idea, and should be avoided.

I wouldn't say that. For example std::unique_lock performs a system call in its constructor.

@ilg-ul
Copy link
Contributor

ilg-ul commented Jan 6, 2021

For example std::unique_lock performs a system call in its constructor

What call?

@LnnrtS
Copy link
Contributor Author

LnnrtS commented Jan 6, 2021

It locks the mutex you pass it which in turn interacts with the os.
(I would say that is a system call but maybe we are talking about different things then)

@ilg-ul
Copy link
Contributor

ilg-ul commented Jan 6, 2021

Does it work when called from a static constructor on Linux?

@ilg-ul
Copy link
Contributor

ilg-ul commented Jan 6, 2021

And related: on Linux, is main() running from a thread?

@LnnrtS
Copy link
Contributor Author

LnnrtS commented Jan 6, 2021

Honestly I don't know that.

But my understanding is that everything in userspace is 'running from a thread'. When you call a c++ program, some thread context is created, execution starts from the entry point of the executable which directly calls into libc and libc++ which in turn calls init functions and finally calls main. At every point you should be able make system calls because its not the system that gets bootstrapped but the c++ environment. In our case its more complicated because system and c++ bootstrapping are mixed together.

@ilg-ul
Copy link
Contributor

ilg-ul commented Jan 6, 2021

If on Linux the static constructors also run from a thread, then we should investigate this route too.

@ilg-ul
Copy link
Contributor

ilg-ul commented Jan 6, 2021

I did some reading and indeed, initialising static code in multithreaded environments seem a tough subject in C++.

There is also a good article on singletons:

Moving the static constructors initialisations on the main thread probably is not that difficult, but protecting static initialisations in a function which may be called from two threads needs some attention.

We probably have to revisit some parts of the system.

@LnnrtS
Copy link
Contributor Author

LnnrtS commented Jan 6, 2021

That's an interesting paper on an aspect I haven't thought about much before.

But I would say its is outdated. C++11 added general thread awareness to language, so as stated in the reference initialization of static local statics is guaranteed to be thread safe - Unless you don't disable it in the compiler (-fno-threadsafe-statics in gcc)

@ilg-ul
Copy link
Contributor

ilg-ul commented Jan 6, 2021

static local statics is guaranteed to be thread safe

Well it is guaranteed as long as the runtime implements correctly the guard functions, which in µOS++ is not done, and, if I remember right, my projects disable this feature, to avoid other issues.

Definitely something to improve.

@ilg-ul
Copy link
Contributor

ilg-ul commented Jan 6, 2021

For reference, here is one of the glibc startup files:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants