kernel: make gint_setrestart() reset everything

This commit is contained in:
Lephe 2022-09-02 22:29:19 +02:00
parent 9924dc4684
commit 3e5c45c5ad
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
3 changed files with 37 additions and 26 deletions

View file

@ -59,14 +59,23 @@ void gint_world_sync(void);
call to getkey(), but can also be called manually. */
void gint_osmenu(void);
/* gint_osmenu_native(): Like gint_osmenu() without the world switch
This is a replacement for gint_osmenu() which can be used when the current
kernel is already the native OS kernel. */
void gint_osmenu_native(void);
/* gint_setrestart(): Set whether to restart the add-in after exiting
An add-in that reaches the end of its code exits. On the calculator, except
using OS-dependent settings, it cannot be started again unless another
application is launched first.
An add-in that returns from its main() function automatically exits to the
OS' main menu. However, when this happens the OS does not allow the add-in
to be restarted unless another add-in is launched first. (This is because
the OS tries to *resume* the current add-in, which then proceeds to exit
again immediately.)
This setting allows the add-in to restart by calling gint_osmenu() instead
of exiting. This can give a proper illusion of restarting if used correctly.
This function enables a gint trick where after main() returns the add-in
will invoke the main menu with gint_osmenu() rather than exiting. If the
add-in is selected again, gint will jump back to the entry point, creating
the illusion that the add-in exited and was then restarted.
@restart 0 to exit, 1 to restart by using gint_osmenu() */
void gint_setrestart(int restart);

View file

@ -23,7 +23,7 @@ static void __osmenu_handler(void)
__Timer_Deinstall(__osmenu_id);
}
static void __osmenu(void)
void gint_osmenu_native(void)
{
__ClearKeyBuffer();
@ -70,5 +70,5 @@ static void __osmenu(void)
/* gint_osmenu() - switch out of gint and call the calculator's main menu */
void gint_osmenu(void)
{
gint_world_switch(GINT_CALL(__osmenu));
gint_world_switch(GINT_CALL(gint_osmenu_native));
}

View file

@ -94,11 +94,7 @@ static void callarray(void (**f)(void), void (**l)(void))
while(f < l) (*(*f++))();
}
/* start(): Where it all starts
Returns a status code. Invoking main menu is better than returning, see
gint_setrestart() for that. */
GSECTION(".text.entry")
int start(int isappli, int optnum)
static int start2(int isappli, int optnum)
{
/* We are currently in a dynamic userspace mapping of an add-in run
from the storage memory. We are running in privileged mode with one
@ -179,8 +175,6 @@ int start(int isappli, int optnum)
hosted user application, which has its own constructors and
destructors to work with. */
while(1)
{
/* Here, we use exit() to allow the standard library to do
what it wants in exit() after main() finishes executing */
if(!setjmp(gint_exitbuf)) {
@ -191,10 +185,6 @@ int start(int isappli, int optnum)
callarray(&bdtors, &edtors);
}
if(!gint_restart) break;
gint_osmenu();
}
/* Before leaving the application, we need to clean everything we
changed to hardware settings and peripheral modules. The OS is bound
to be confused (and hang, or crash, or any other kind of giving up)
@ -206,6 +196,18 @@ int start(int isappli, int optnum)
return gint_exitcode;
}
GSECTION(".text.entry")
int start(int isappli, int optnum)
{
int rc;
while(1) {
rc = start2(isappli, optnum);
if(!gint_restart) break;
gint_osmenu_native();
}
return rc;
}
/* Standard _Exit, used by the fxlibc exit() to leave control */
void _Exit(int rc)
{