world: new gint_world_enter() and gint_world_leave() primitives

This commit is contained in:
Yann MAGNIN 2025-04-01 15:03:23 +02:00
parent dff487b20a
commit 4442d27b62
No known key found for this signature in database
GPG key ID: D82629D933EADC59
3 changed files with 62 additions and 2 deletions

View file

@ -41,6 +41,15 @@ int gint_world_switch(gint_call_t function);
__attribute__((deprecated("Use gint_world_switch() instead"))) __attribute__((deprecated("Use gint_world_switch() instead")))
void gint_switch(void (*function)(void)); void gint_switch(void (*function)(void));
#define GINT_WORLD_ADDIN 1
#define GINT_WORLD_OS 0
/* gint_world_enter(): Enter in a new world */
void gint_world_enter(int world);
/* gint_world_leave(): Leave a world set by gint_world_enter() */
void gint_world_leave(void);
/* gint_world_sync(): Synchronize asynchronous drivers /* gint_world_sync(): Synchronize asynchronous drivers
This function waits for asynchronous tasks to complete by unbinding all This function waits for asynchronous tasks to complete by unbinding all

View file

@ -81,6 +81,7 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
if(code == 0x1080) name = "Stack overflow"; if(code == 0x1080) name = "Stack overflow";
if(code == 0x10a0) name = "UBC in bank 1 code"; if(code == 0x10a0) name = "UBC in bank 1 code";
// if(code == 0x10c0) name = "Missing syscall"; // not on FX // if(code == 0x10c0) name = "Missing syscall"; // not on FX
if(code == 0x1100) name = "World-switch error";
if(name[0]) dtext(1, 9, name); if(name[0]) dtext(1, 9, name);
else dprint(1, 9, "%03x", code); else dprint(1, 9, "%03x", code);
@ -124,6 +125,7 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
if(code == 0x10a0) name = "UBC break in register bank 1 code"; if(code == 0x10a0) name = "UBC break in register bank 1 code";
if(code == 0x10c0) name = "Missing syscall for this OS version"; if(code == 0x10c0) name = "Missing syscall for this OS version";
if(code == 0x10e0) name = "I2C (touch-screen) error"; if(code == 0x10e0) name = "I2C (touch-screen) error";
if(code == 0x1100) name = "World-switch error";
dprint(6, 25, "%03x %s", code, name); dprint(6, 25, "%03x %s", code, name);

View file

@ -3,6 +3,7 @@
#include <gint/gint.h> #include <gint/gint.h>
#include <gint/exc.h> #include <gint/exc.h>
#include <gint/defs/call.h> #include <gint/defs/call.h>
#include <gint/defs/util.h>
#include <gint/hardware.h> #include <gint/hardware.h>
#include <gint/display.h> #include <gint/display.h>
#include "kernel.h" #include "kernel.h"
@ -146,10 +147,58 @@ void gint_world_switch_out(gint_world_t world_addin, gint_world_t world_os)
cpu_atomic_end(); cpu_atomic_end();
} }
#ifndef WORLD_SWITCH_STACK_SIZE
# define WORLD_SWITCH_STACK_SIZE 8
#endif
static struct {
u8 stack[WORLD_SWITCH_STACK_SIZE];
int idx;
} world_switch_stack = {
.stack = { GINT_WORLD_ADDIN },
.idx = 0,
};
// FIXME: support CPU atomic operation
void gint_world_enter(int world)
{
GAUTOTYPE wss = &world_switch_stack;
if (world != GINT_WORLD_OS && world != GINT_WORLD_ADDIN)
gint_panic(0x1100);
if (wss->idx >= WORLD_SWITCH_STACK_SIZE)
gint_panic(0x1100);
if (world != wss->stack[wss->idx])
{
if (world == GINT_WORLD_OS)
gint_world_switch_out(gint_world_addin, gint_world_os);
if (world == GINT_WORLD_ADDIN)
gint_world_switch_in(gint_world_os, gint_world_addin);
}
wss->stack[++(wss->idx)] = world;
}
// FIXME: support CPU atomic operation
void gint_world_leave(void)
{
GAUTOTYPE wss = &world_switch_stack;
if (wss->idx == 0)
gint_panic(0x1100);
if (wss->stack[wss->idx - 0] != wss->stack[wss->idx - 1])
{
if (wss->stack[wss->idx] == GINT_WORLD_OS)
gint_world_switch_in(gint_world_os, gint_world_addin);
if (wss->stack[wss->idx] == GINT_WORLD_ADDIN)
gint_world_switch_out(gint_world_addin, gint_world_os);
}
wss->idx -= 1;
}
int gint_world_switch(gint_call_t call) int gint_world_switch(gint_call_t call)
{ {
extern void *gint_stack_top; extern void *gint_stack_top;
gint_world_switch_out(gint_world_addin, gint_world_os); gint_world_enter(GINT_WORLD_OS);
void *ILRAM = (void *)0xe5200000; void *ILRAM = (void *)0xe5200000;
void *XRAM = (void *)0xe500e000; void *XRAM = (void *)0xe500e000;
@ -194,7 +243,7 @@ int gint_world_switch(gint_call_t call)
if(canary && *canary != 0xb7c0ffee) if(canary && *canary != 0xb7c0ffee)
gint_panic(0x1080); gint_panic(0x1080);
gint_world_switch_in(gint_world_os, gint_world_addin); gint_world_leave();
return rc; return rc;
} }