Open LnnrtS opened 3 years ago
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.
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.
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.
For example
std::unique_lock
performs a system call in its constructor
What call?
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)
Does it work when called from a static constructor on Linux?
And related: on Linux, is main()
running from a thread?
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.
If on Linux the static constructors also run from a thread, then we should investigate this route too.
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.
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)
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.
For reference, here is one of the glibc startup files:
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 withmutex
). 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
os_run_init_array()
from the main threadLooking forward to hearing your thoughts on this