The traditional type signature (argc, argv**, argp**) doesn't make a ton of sense for Tock (or does it? Maybe in some world it will make sense to have precompiled binaries with runtime options expressed by arguments set up by the application loader - leveraging the "traditional" mechanism might be the right way to do that)
Currently, it's a (void*, void*, void*) that passes main(mem_start, app_heap_break, kernel_memory_break); that most apps just ignore (i.e. int main(void) {), however, with LTO the compiler will no longer silently ignore the mismatch:
../../libtock/crt1.c:9:12: warning: type of 'main' does not match original declaration [-Wlto-type-mismatch]
extern int main(void*, void*, void*);
^
main.c:6:5: note: type mismatch in parameter 1
int main(void) {
^
main.c:6:5: note: 'main' was previously declared here
I'm pretty confident the only two apps that use the current main definition are tests/mpu_stack_growth and tests/mpu_walk_region. Prior to me writing those, main was just empty everywhere, and that was arguably somewhat of a hack just to see what's going on (one could easily imagine syscalls to get the same information, if we even want to expose those values to processes)
What should the type signature for main be for userland Tock?
Definitely _not_ POSIX-style char** argv etc...
Since in practice the init function is very simple and marked weak, I think it's perfectly reasonable to use void main(void) instead (not int main, the return value is meaningless), and just rewrite those tests to override init.
It's actually not weak right now, but it probably could/should be:
https://github.com/helena-project/tock/blob/master/userland/libtock/crt1.c#L16
__attribute__ ((section(".start"), used))
__attribute__ ((noreturn))
void _start(
void* mem_start,
void* app_heap_break,
void* kernel_memory_break) {
main(mem_start, app_heap_break, kernel_memory_break);
while(1) { yield(); }
}
In addition, based on what the actual _function_ of main is, maybe it should be called something like init instead, since, kind of the whole point is to initialize asynchronous operations and return.
Well, initialization is not always the style. Some of signpost's apps are now ending with a while 1 that does work and then calls delay_ms.
Example:
https://github.com/lab11/signpost/blob/master/software/apps/audio_module/loud_detect_and_post/main.c
yeah, @brghena, which is totally fine, but realistically they could just override _start. The problem with the name main is the returning from it tends to imply you're exiting.
Would it be appropriate to move to more Arduino style names, an init and loop method (where in Amit's case, the user simply doesn't define a loop function)
well... i certainly like that it's possible to write that program, but I think it should be a library on top or something. In particular because it's such little code to write on your own:
void _start(
void* mem_start,
void* app_heap_break,
void* kernel_memory_break) {
init();
while(1) {
yield();
loop();
}
}
The problem with the name main is the returning from it tends to imply you're exiting.
I would argue the name main implies that is where the main code is. I see no reason to change from convention.
As for the arguments, I could imagine passing each app the board name, or a list of valid driver numbers, or something else the app creator may want to switch on. However, it seems easier to define those as syscalls at some point in the future, rather than trying to come up with the correct standard app start function call now.